当前位置: 首页 > news >正文

Android显示学习笔记本

根据博客 Android-View 绘制原理(01)-JAVA层分析_android view draw原理分析-CSDN博客

提出了我的疑问  Canvas RenderNode updateDisplayListDirty 这些东西的关系

您的理解在基本方向上是对的,但让我详细解释一下 Android 中 updateDisplayListDirty、指令集合、Canvas 和 RenderNode 之间的关系:

RenderNode 与渲染过程

在 Android 的渲染系统中:

  1. RenderNode
    • 是一个存储渲染操作的容器
    • 包含了视图的绘制命令和属性信息
    • 可以被缓存和重用,提高渲染效率
  2. DisplayList
    • 实际上是 RenderNode 内部的绘制命令列表
    • 存储了一系列需要执行的渲染指令
    • 通过 updateDisplayListDirty 方法更新这些指令
  3. Canvas
    • 是应用层与渲染系统交互的接口
    • 提供了各种绘制方法(drawRect、drawText 等)
    • 当我们调用 Canvas 的绘制方法时,它会转换为渲染指令

updateDisplayListDirty 与 Canvas 的关系

updateDisplayListDirty 方法在 View 类中实现,主要作用是:

  1. 创建或获取一个 RenderNode
  2. 使用 DisplayListCanvas(特殊的 Canvas 实现)录制绘制指令
  3. 当视图调用 onDraw() 方法时,它使用提供的 Canvas 执行绘制
  4. 这些绘制命令被记录到 DisplayList 中
  5. 最终生成或更新 RenderNode

Canvas 和 DisplayList 不是可替代关系,而是协作关系:

  • Canvas 是绘制接口,应用通过它表达"画什么"
  • DisplayList 是指令集合,记录"如何画"
  • RenderNode 是整个结构的容器,包含了 DisplayList 和其他渲染属性

所以不是"有一个就可以了",而是它们在渲染管线中扮演不同角色:Canvas 是应用用来绘制的工具,而 DisplayList 是记录这些绘制指令的容器,两者共同构成了 Android 的高效渲染系统。

 看完后我的疑问变成了,既然 updateDisplayListDirty  是一个指令集合 在硬件加速的情况下,一个渲染当VSYNC信号来了,进行三大流程进行获取surfaceControl然后进行 绘制,绘制时候先新建RenderNode 然后获取 RenderNode 的 

RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
RecordingCanvas 然后把它变成后续的 Canvas
最后  

   public void endRecording() {if (mCurrentRecordingCanvas == null) {throw new IllegalStateException("No recording in progress, forgot to call #beginRecording()?");}RecordingCanvas canvas = mCurrentRecordingCanvas;mCurrentRecordingCanvas = null;canvas.finishRecording(this);canvas.recycle();}

finishRecording 把 当前的 RenderNode 传过去 然后进行绘制

那么我的问题是 之后surfaceFlinger是否绘制的是指令集合?是否是当RecordingCanvas  执行一次生成一个指令就绘制一部分还是 finishRecording 后一起进行绘制?

您的问题涉及到 Android 渲染流水线的关键细节,我来详细解释:

finishRecording 与渲染流程

在 Android 的硬件加速渲染流程中,当 finishRecording() 被调用时:

  1. 指令集完成阶段
    • finishRecording() 标志着 RecordingCanvas 已经完成所有绘制命令的记录
    • 此时,所有来自 onDraw() 的绘制操作已经被转换为渲染指令并存储在 RenderNode 中
    • 这些指令并不会立即触发绘制
  2. 批处理渲染模式
    • SurfaceFlinger 不会 在每条指令生成后立即渲染
    • 系统采用批处理模式,收集完所有指令后一次性处理
    • 这种方式大大提高了渲染效率,避免了频繁的状态切换和上下文切换
  3. 渲染时机
    • ViewRootImpl.performTraversals() 完成后,会调用 ThreadedRenderer.draw()
    • 此时,所有视图的 RenderNode 都已准备就绪
    • 系统会将这些渲染命令通过 HWUI 传递给 GPU
    • SurfaceFlinger 会在下一个 VSYNC 信号到来时合成并显示结果
  4. SurfaceFlinger 处理
    • SurfaceFlinger 接收的是已经处理过的图层数据
    • 它主要负责合成多个应用的图层,而不是执行具体的绘制指令
    • 实际的指令执行发生在 GPU 上,在应用进程的渲染线程中

所以,回答您的核心问题:系统是在 finishRecording() 后,将完整的指令集合一次性提交给渲染管线进行处理,而不是每生成一条指令就执行一次渲染。这种批处理模式是现代图形渲染系统的普遍做法,可以最大限度地减少 GPU 状态切换,提高渲染效率。

需要注意的是,RecordingCanvas 记录的指令集和 SurfaceFlinger 处理的内容在概念上有区别——前者是应用内的绘制指令,后者处理的是已经渲染好的图层。

 

那这些指令在哪被处理?

这些渲染指令的处理发生在多个层次的渲染管线中,让我详细解释这个流程:

渲染指令的处理路径

  1. 应用进程中的处理
    • finishRecording() 完成后,渲染指令首先在应用自己的渲染线程中处理
    • ThreadedRenderer 类负责协调这个过程
    • 具体处理由 HWUI (Hardware User Interface) 库在原生层完成
    • 在这一阶段,渲染指令被转换为 GPU 可以理解的命令(如 OpenGL ES 或 Vulkan 调用)
  2. RenderThread 中的执行
    • Android 使用专门的 RenderThread(渲染线程)处理这些指令
    • 这个线程与主线程分离,可以并行处理渲染工作
    • 渲染指令在这里被组织成命令缓冲区(Command Buffer)
    • 这些命令最终会通过图形驱动提交给 GPU
  3. GPU 执行阶段
    • GPU 接收这些渲染命令并执行实际的像素处理
    • 渲染结果被写入到应用的 Surface 对应的图形缓冲区中
    • 这个过程完全由 GPU 硬件加速完成
  4. SurfaceFlinger 的角色
    • SurfaceFlinger 不处理原始渲染指令,而是处理已渲染好的图层
    • 它从各个应用获取已经渲染好的图形缓冲区
    • 然后进行合成(Composition)操作,决定不同应用的图层如何叠加显示
    • 最后将合成结果提交给显示硬件

具体源码路径

如果您想在源码中追踪这个处理过程:

  1. ThreadedRenderer.nSyncAndDrawFrame() 是关键的入口点,它通过 JNI 调用原生层代码
  2. 在原生层,android_view_ThreadedRenderer.cpp 包含了相关实现
  3. 进一步深入到 libs/hwui/ 目录,特别是 RenderProxyRenderThread 相关类
  4. 最终的 GPU 命令提交通过图形驱动 API(如 OpenGL ES 或 Vulkan)完成

所以,渲染指令主要在应用自己的渲染线程中被处理和执行,而不是在 SurfaceFlinger 中。SurfaceFlinger 的工作是在所有应用都完成各自的渲染后,组合这些结果并显示到屏幕上。

http://www.xdnf.cn/news/198721.html

相关文章:

  • 打造即插即用的企业级云原生平台——KubeSphere 4.1 扩展组件在生产环境的价值全解
  • 解决跨域实现方案
  • 用vite动态导入vue的路由配置
  • 本地部署Qwen-7B实战 vLLM加速推理
  • 网络协议之为什么要分层
  • 论文分享 | 基于区块链和签名的去中心化跨域认证方案
  • 受限字符+环境变量RCE
  • vue3:v-model的原理示例
  • python练习:求数字的阶乘
  • 思科bsp社招面试
  • JavaScript 与 Java 学习笔记
  • day9 python 热力图与子图的绘制
  • MYSQL——时间字段映射Java类型
  • 庙算兵棋推演AI开发初探(7-神经网络训练与评估概述)
  • FTP-网络文件服务器
  • 使用 Vue3 + Webpack 和 Vue3 + Vite 实现微前端架构(基于 Qiankun)
  • iVX 图形化编程如何改写后端开发新范式
  • EXCEL中跨行匹配两组数据
  • 流域生态系统碳排放、碳循环模拟与评估技术应用
  • 【基础篇】static_config采集配置详解
  • Vue 3 中通过 createApp 创建的 app 实例的所有核心方法,包含完整示例、使用说明及对比表格
  • 深入解析 PyTorch 中的 torch.distributions模块与 Categorical分布
  • 2025吃鸡变声器软件推荐
  • 【Vue3 组合式 API 在大型项目中的实践:useOperatorData 封装与应用】
  • 如何开发动态贴纸功能?一体化美颜SDK的技术实现思路与实战方案
  • Java 入门宝典--注释、关键字、数据类型、变量常量、类型转换
  • 服务器部署,Nginx安装和配置
  • 思维链理解汇总
  • 美团社招一面
  • 2025天津二类医疗器械经营备案攻略