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

android 渲染流水线中的两个重要阶段:swapBuffers 和 DrawFrames

一、问题一
📱 Android HWUI 的 swapBuffers 是什么作用?
在 Android 的图形系统中,swapBuffers 是一个关键的渲染阶段,其作用如下:

✅ 简要定义
swapBuffers() 会将当前绘制完成的图像缓冲区(Frame Buffer)提交给 SurfaceFlinger 合成并显示到屏幕上。

🧱 作用详解

  1. 双缓冲机制中的“交换缓冲”
    Android 使用 双缓冲(或三缓冲)机制 来避免撕裂(tearing)和提升流畅度:

swapBuffers() 的调用意味着:
将当前渲染的后备缓冲区(back buffer)变成前台缓冲区(front buffer),交由系统显示

同时,GPU 会获取新的缓冲区来继续绘制下一帧。

  1. Android HWUI 调用链中的位置
    当你使用 Jetpack Compose、View、Canvas、OpenGL 等方式渲染 UI 时,HWUI(即 android.graphics.RenderThread + Skia)负责将界面绘制到 GraphicBuffer 上。绘制完成后,会调用:
eglSwapBuffers(display, surface); // EGL 层调用

该函数最终会触发底层的 swapBuffers(),将这一帧提交到系统用于显示。

  1. 触发 SurfaceFlinger 合成(VSYNC 对齐)
    swapBuffers() 是连接应用绘制与系统合成(SurfaceFlinger)的桥梁

通常会与 VSYNC 同步,以避免卡顿、撕裂等显示问题

在这里插入图片描述

二、问题二
🎨 Android RenderThread 中的 DrawFrames 是什么作用?
非常好的问题!你提到的 DrawFrames 确实是 Android 渲染系统中的一个重要部分,它与 HWUI(Hardware UI) 密切相关,但它的作用不是构建 Display List,而是执行 Display List 的实际绘制操作。

✅ 简要回答
RenderThread 中的 DrawFrames 是用于:

执行绘制任务(即将 Display List 绘制到 GPU 缓冲区)

然后调用 swapBuffers,将内容提交给 SurfaceFlinger 合成显示

🧠 它不是构建 Display List,而是:
DisplayList 是在主线程构建的(通过 View 的 draw() 方法、Jetpack Compose、Canvas 等)

构建完成后,通过 Choreographer 的 VSYNC 调度信号,将 DisplayList 交给 RenderThread 去执行 DrawFrames

DrawFrames 是 真正的 GPU 绘制执行点

🔍 更详细的流程:
🌿 1. 构建阶段(主线程)
App 的 UI 树(View 或 Compose)会在主线程中被遍历、测量、布局

接着构建 Display List(一个记录绘图操作的列表,类似 Skia 的 SkPicture)

🔄 2. 提交到 RenderThread
主线程将 DisplayList 提交给 RenderProxy

RenderProxy 是 HWUI 的 Java <-> C++ 桥梁,位于:

android.view.ThreadedRenderer

🚀 3. RenderThread::DrawFrames()
该阶段由 Choreographer 或 VSYNC 信号触发,关键代码如下:

void DrawFrameTask::run() {...canvas->draw(displayList);   // 执行绘图指令eglManager.swapBuffers();    // 提交显示
}

✅ 在这个过程中:
Skia GPU Backend(如 SkiaGL)负责实际绘制

输出图像到 GPU 的 Framebuffer(GraphicBuffer)

最终流程是:

swapBuffers() → SurfaceFlinger → 屏幕显示

在这里插入图片描述

http://www.lryc.cn/news/572576.html

相关文章:

  • 【Oracle专栏】ORA-04036 报错 PGA设置
  • Android开发常用adb合集
  • 医疗AI大数据处理流程的全面解析:从数据源到应用实践
  • SSE 流与普通 HTTP 响应的区别
  • 防抖不同的实现
  • 领码 SPARK 融合平台赋能工程建设行业物资管理革新——数智赋能,重塑中国模式新范式
  • 阿里云OSS对象云储存入门操作
  • 【Leetcode】字符串之二进制求和、字符串相乘
  • 智能危险品搬运机器人市场报告:行业趋势与未来展望
  • 深度学习笔记27-LSTM实现糖尿病探索与预测(Pytorch)
  • 华为云Flexus+DeepSeek征文 | 利用Dify平台构建多智能体协作系统:从单体到集群的完整方案
  • SpringMVC知识点总结
  • C++网络编程入门学习(五)-- CMake 学习笔记
  • iOS应用启动时间优化:通过多工具协作提升iOS App性能表现
  • 在 Windows 上使用 Docker Desktop 快速搭建本地 Kubernetes 环境(附详细部署教程)
  • 【支持向量机】SVM线性可分支持向量机学习算法——硬间隔最大化支持向量机及例题详解
  • 退出python解释器的四种方式
  • Android中Native向System Service进行Binder通信的示例
  • 解决 Docker 里 DrissionPage 无法连接浏览器的问题,内含直接可用的Docker镜像(DrissionPage 浏览器链接失败 怎么办?)
  • 机构运动分析系统开发(Python实现)
  • WPF xaml 中设置ResourceDictionary中的全局变量
  • JS红宝书笔记 8.2 创建对象
  • 李宏毅《生成式人工智能导论》| 第1讲:什么是生成式人工智能
  • python画三维立体图
  • SpringBoot扩展——应用Web Service!
  • 简单理解HTTP/HTTPS协议
  • C#语言入门-task2 :C# 语言的基本语法结构
  • Python训练营打卡 Day55
  • C++实现手写strstr函数
  • 12.10 在主线程或子线程中更新 UI