Top Banner
Beyond Android Views - Window, Surface, Special Views and More Roger [email protected] [email protected] www.twitter.com/roger2yi +易易易 in Google+
48

Beyond Android Views - Window,Surface,Special Views,and More

May 10, 2015

Download

Technology

rogeryi

Introduce Android Graphics System
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 2: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 3: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 4: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 5: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 6: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 7: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 8: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 9: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 10: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 11: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 12: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 13: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 14: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 15: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 16: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 17: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 18: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 19: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 20: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 21: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 22: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 23: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 24: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 25: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 26: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 27: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 28: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 29: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 30: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 31: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 32: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 33: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 34: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 35: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 36: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 37: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 38: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 39: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 40: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 41: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 42: Beyond Android Views - Window,Surface,Special Views,and More

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

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 43: Beyond Android Views - Window,Surface,Special Views,and More

Reference

bull Android 圖形系統 -- 設計與實做分析

bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich

The End

Thank you for your listeningYours Sincerely Roger

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48
Page 44: Beyond Android Views - Window,Surface,Special Views,and More

The End

Thank you for your listeningYours Sincerely Roger

  • Slide 1
  • Slide 2
  • Slide 3
  • Slide 4
  • Slide 5
  • Slide 6
  • Slide 7
  • Slide 8
  • Slide 9
  • Slide 10
  • Slide 11
  • Slide 12
  • Slide 13
  • Slide 14
  • Slide 15
  • Slide 16
  • Slide 17
  • Slide 18
  • Slide 19
  • Slide 20
  • Slide 21
  • Slide 22
  • Slide 23
  • Slide 24
  • Slide 25
  • Slide 26
  • Slide 27
  • Slide 28
  • Slide 29
  • Slide 30
  • Slide 31
  • Slide 32
  • Slide 33
  • Slide 34
  • Slide 35
  • Slide 36
  • Slide 37
  • Slide 38
  • Slide 39
  • Slide 40
  • Slide 41
  • Slide 42
  • Slide 43
  • Slide 44
  • Slide 45
  • Slide 46
  • Slide 47
  • Slide 48