Android 14 HWUI 源码研究 View Canvas RenderThread ViewRootImpl skia

HWUI 整体架构

HWUI主要功能是完成应用程序可视化元素绘制,核心代码位于framework c++层,承接Java层View绘制信息,开启进程唯一的渲染线程,借用skia绘制能力,完成渲染。

整体模块流程

Application-Activity-HWUI层级关系

注意:一个进程对应唯一的渲染线程,UI线程和渲染线程有个同步操作。

HWUI核心类和层级关系

容易混淆的Canvas关系

理解的核心:Canvas用来收集View的绘制信息,为了解耦才搞得这么多名字。

Canvas层级和对应关系

Java层两类Canvas:RecordingCanvas和Canvas。

  • RecordingCanvas直接对应C++层SkiaRecordingCanvas,SkiaRecordingCanvas实际使用RecordingCanvas记录指令
  • Canvas直接对应C++层SkiaCanvas,SkiaCanvas直接引用SkCanvas。
  • RecordingCanvas纯做指令记录

重要对象创建入口:

最左侧给出源码层面各主要对象调用入口。

()表示构造函数里创建右侧对象。

xx()表示正常函数里调用创建右侧对象。

其它:

RecordingCanvas负责指令记录动作,RenderNode 负责保存指令记录结果和渲染属性。

RenderProxy RenderThread CanvasContext IRenderPipeline负责指令渲染

全局大循环

协作关系:

细节待补充:Activity PhoneWindow WindowManagerGlobal DecorView ViewRootImpl

Window和View体系区别:

DecorView是View根节点,activity setContentView是DecorView子节点

ViewRootImpl衔接Window和View,并且负责View更新、渲染。

View相关的几大流程:

new Activity() -> attach() -> new PhoneWindow()待补充细化,对应"开始1 "

addView把View添加到渲染线程,待补充细节,对应"开始2"

performTranversals()

全局刷新流程,包含measure layout draw复杂子流程

performDraw()

触发指令记录和指令渲染流程

* beginRecording 创建Java::RecordingCanvas和C++::SkiaRecordingCanvas * updateRootDisplayList() 触发指令录制动作,用RecordingCanvas完成View到DisplayList转换 * endRecording() 把SkiaRecordingCanvas记录的指令,统一转存到RenderNode里

* syncAndDrawFrame() 指令线程同步和渲染。涉及到C++层RenderProxy RenderThread DrawFrameTask CanvasContext重要对象

渲染线程创建流程和核心对象

RenderProxy衔接Java层信息

RenderThread进程唯一的渲染线程

DrawFrameTask一帧绘制逻辑

CanvasContext负责一帧具体的绘制

指令记录流程

核心是把View的属性和绘制信息,通过C++层RecordingCanvas记录到DisplayList中

指令同步流程

指令渲染流程

Surface -> ANativeWindow -> EGLSurface画布创建流程

  • 初始化入口在ViewRootImpl.performTraversals()大函数里
  • 为什么用ReliableSurface封装一下,没深入研究
  • EGL和Skia环境创建主要在RenderThread.requireGlContext()函数
  • 从源码分析,一共三个地方地方调用requireGlContext()

View树和RenderNode树

类协作关系

协作

  • 一个Application进程,对应多个Activity,一个Activity一一对应PhoneWindow
  • PhoneWindow唯一持有一个DecorView
  • DecorView一一对应ViewRootImpl
  • ViewRootImpl创建并持有ThreadedRender
  • ThreadedRender与C++层RenderProxy一一对应
  • RenderProxy负责渲染代理,持有三个重要对象RenderThread、CanvasContext、DrawFrameTask
  • RenderThread是渲染线程,是单态模式,进程唯一
  • Activity.setContentView() -> PhoneWindow.setContentView(),把View挂到DecorView子节点上。
  • WindowManagerImpl.addView()设置给ViewRootImpl,并与ThreadedRender模块对接

RenderNode

  • 用于保存渲染属性和渲染指令
  • mStagingProperties和mStagingDisplayList只在MainThread修改
  • mProperties和mDisplayList只在RenderThread使用
  • 数据同步发生在DrawFrameTask的run()函数,详见"指令同步"小节

其它:

PhoneWindow DialogWindow SubMenuWindow ---> Window

PhoneWindow是Activity和View交互中间层,帮助Activity管理View

RenderPipeline模块

执行渲染模块相对结构清晰,重点关注:

  • makeCurrent()
  • draw()
  • swapBuffers()

Native Canvas关系

  • SkiaRecordingCanvas起到桥接作用,对上接收Java api调用
  • RecordingCanvas完成Op记录
  • DisplayListData真正存储Op的地方

skia核心资源三个使用场景

相关推荐
阿巴斯甜1 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿2 天前
Android MediaPlayer 笔记
android
Jony_2 天前
Android 启动优化方案
android
阿巴斯甜2 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇2 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_2 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android