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核心资源三个使用场景

相关推荐
一只柠檬新3 小时前
Web和Android的渐变角度区别
android
志旭3 小时前
从0到 1实现BufferQueue GraphicBuffer fence HWC surfaceflinger
android
_一条咸鱼_3 小时前
Android Runtime堆内存架构设计(47)
android·面试·android jetpack
用户2018792831674 小时前
WMS(WindowManagerService的诞生
android
用户2018792831674 小时前
通俗易懂的讲解:Android窗口属性全解析
android
openinstall4 小时前
A/B测试如何借力openinstall实现用户价值深挖?
android·ios·html
二流小码农4 小时前
鸿蒙开发:资讯项目实战之项目初始化搭建
android·ios·harmonyos
志旭5 小时前
android15 vsync源码分析
android
whysqwhw5 小时前
Egloo 高级用法
android