【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-display
- [1. 概述](#1. 概述)
-
- [1.1 文档目的](#1.1 文档目的)
- [1.2 代码版本与范围](#1.2 代码版本与范围)
- [1.3 03 系列子文档地图](#1.3 03 系列子文档地图)
- [2. `lv_display_t` 的角色与生命周期](#2.
lv_display_t的角色与生命周期) -
- [2.1 `lv_display_t` 是什么](#2.1
lv_display_t是什么) - [2.2 创建与销毁过程(高层视角)](#2.2 创建与销毁过程(高层视角))
- [2.1 `lv_display_t` 是什么](#2.1
- [3. 显示刷新链路总览(display pipeline)](#3. 显示刷新链路总览(display pipeline))
-
- [3.1 从对象失效到 flush_cb:ASCII 流程示意](#3.1 从对象失效到 flush_cb:ASCII 流程示意)
- [3.2 render_mode 与 buffer 配置的影响(概览)](#3.2 render_mode 与 buffer 配置的影响(概览))
- [4. `_lv_display_t` 关键模块总览](#4.
_lv_display_t关键模块总览) -
- [4.1 分辨率与坐标系统](#4.1 分辨率与坐标系统)
- [4.2 画布缓冲与 display pipeline](#4.2 画布缓冲与 display pipeline)
- [4.3 层与屏幕(Layer & Screen)](#4.3 层与屏幕(Layer & Screen))
- [4.4 旋转与主题](#4.4 旋转与主题)
- [4.5 调试与监控](#4.5 调试与监控)
- [5. 与 draw/tick 的调用关系(高层时序)](#5. 与 draw/tick 的调用关系(高层时序))
- [6. 移植与调优的整体建议](#6. 移植与调优的整体建议)
-
- [7. 附录](#7. 附录)
-
- [A. 参考文档(外部)](#A. 参考文档(外部))
- [B. 相关资源(外部)](#B. 相关资源(外部))
文档版本 : 1.0
更新日期 : 2025年11月
适用对象: LVGL9.4 显示驱动/移植工程师、需要整体把握显示框架的开发人员
1. 概述
1.1 文档目的
本篇作为 【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-* 系列的总览篇 ,从整体层面对 LVGL9.4 的
display/display driver 相关源码进行梳理,帮助读者:
- 搭建对显示框架的"全景图"认识,理解
lv_display_t在系统中的角色; - 把握刷新链路的关键阶段:分辨率、缓冲区、渲染模式、flush 回调、局部刷新与图层叠加等;
- 理解显示框架与 draw 模块、tick/定时器之间的调用关系;
- 知道后续子文档(分辨率管理、画布缓冲管理、局部刷新与脏区、图层管理、旋转方案、主题管理、内存和性能调试)各自负责的细节范围。
1.2 代码版本与范围
- 仓库路径:
https://github.com/lvgl/lvgl.git - 版本:v9.4.0
- commit:
c016f72d4c125098287be5e83c0f1abed4706ee5 - 主要关注源码位置:
src/display/*:display 对象与刷新入口;src/core/lv_refr.c:刷新调度与局部刷新实现;src/draw/*:绘图后端与 draw pipeline;src/others/sysmon/*:性能与内存监控;- 相关结构体:
struct _lv_display_t(lv_display_private.h)及其周边字段。
1.3 03 系列子文档地图
为了避免单篇文章过长,本专题将显示框架拆分为多篇子文档,本篇只做"导读 + 总览":
- 分辨率管理 :
hor_res/ver_res/physical_*/offset_*/dpi等分辨率与坐标相关字段; - 画布缓冲管理 :
buf_1/buf_2/buf_3/buf_act/_static_buf1/2与lv_draw_buf_t尺寸、render_mode 的关系; - 局部刷新和脏区计算规则 :
flushing/render_mode/tile_cnt/inv_areas/sync_areas等刷新控制与脏区算法; - 图层管理 :
layer_head、各种layer_*回调以及 screen/bottom/top/sys layer 的叠加关系; - 旋转方案 :
rotation/matrix_rotation与 display pipeline 中的旋转处理; - 主题管理 :
theme字段与lv_display_set_theme()、默认主题初始化策略; - 内存和性能调试 :
perf_label/mem_label/perf_sysmon_backend/perf_sysmon_info等调试字段。
读者可以先通读本篇,对整体结构有一个清晰印象,再根据实际需求跳转到对应子文档查看细节。
2. lv_display_t 的角色与生命周期
2.1 lv_display_t 是什么
在 LVGL 中,每一个显示输出对应一个 lv_display_t 对象,它承担:
- 显示参数:逻辑/物理分辨率、offset、dpi、颜色格式等;
- 画布缓冲配置:一到三块 draw buffer 指针、active buffer、render_mode 等;
- 刷新驱动钩子 :
flush_cb/flush_wait_cb与refr_timer; - 局部刷新与脏区管理 :
inv_areas/inv_area_joined/inv_p/sync_areas; - 图层与 screen 管理 :
layer_head、screens、act_scr、top_layer、sys_layer等; - 旋转与主题 :
rotation/matrix_rotation/theme; - 调试辅助:性能与内存监控相关字段。
可以把 lv_display_t 理解为**"逻辑显示设备 + 刷新状态 + 调试入口"的组合体**。
2.2 创建与销毁过程(高层视角)
创建 display 的典型流程(伪代码):
c
lv_init();
/* 注册底层显示驱动:framebuffer、SPI LCD、SDL 窗口等 */
my_display_driver_init();
/* 创建 display 对象,这一步内部会: */
lv_display_t * disp = lv_display_create(hor_res, ver_res);
在 lv_display_create() 内部,除了分配 _lv_display_t 本体以外,还会:
- 初始化分辨率/offset/dpi 等字段;
- 初始化 refresh timer(
refr_timer),挂接到lv_display_refr_timer回调; - 创建 bottom/act/top/sys layer 对象,并清理默认样式;
- 在启用主题的情况下,为 display 绑定默认主题;
- 初始化局部刷新、脏区、sync_areas 等数据结构。
显示删除时(lv_display_delete())则逆向回收这些资源,并停止刷新定时器。
3. 显示刷新链路总览(display pipeline)
3.1 从对象失效到 flush_cb:ASCII 流程示意
以应用层触发一次 UI 更新为例,可以用 ASCII 文本画出简化的调用链:
text
应用代码:
修改对象属性 / 状态
│
▼
lv_obj_invalidate(obj)
│
▼
脏区收集:
- 记录需要刷新的区域到 disp->inv_areas[]
- 若使用局部刷新,则可能合并/裁剪多块区域
│
▼
刷新入口:
- 定时器 lv_display_refr_timer() 被 tick 驱动调用
- 或通过 lv_refr_now() 立即触发刷新
│
▼
刷新核心 (lv_refr.c):
- 根据 inv_areas 遍历需要刷新的区域
- 为每个区域配置 lv_layer_t(使用 buf_act / draw_buf)
- 调用 draw backend 将对象树绘制到 buffer
│
▼
驱动 flush:
- 调用 disp->flush_cb(area, color_p)
- 底层驱动/DMA/控制器把 buffer 内容送到物理屏
│
▼
刷新完成:
- 驱动在完成后调用 lv_display_flush_ready(disp)
- 切换双缓冲/三缓冲中的 active buffer(若使用)
- 可能触发下一个区域或下一帧渲染
在这条链上:
lv_display_t提供了刷新所需的所有上下文:缓冲区、分辨率、render_mode 等;lv_refr.c负责 orchestrate(编排)局部刷新与 tile 切分;draw模块专注于把对象树画到当前 active buffer;- display 驱动在
flush_cb里完成"最后一公里",把像素送到屏幕。
3.2 render_mode 与 buffer 配置的影响(概览)
刷新链路会受到两个关键因素影响:
-
render_mode(渲染模式):
LV_DISPLAY_RENDER_MODE_PARTIAL:partial 渲染,只渲染脏区,适合单 buffer 或小 buffer;LV_DISPLAY_RENDER_MODE_FULL:全屏渲染到 buffer,再统一 flush,到屏下缓冲;LV_DISPLAY_RENDER_MODE_DIRECT:直接渲染到显示控制器可见的 buffer,适合双缓冲/三缓冲 + DMA2D/GPU。
-
draw buffer 配置:
- 单 buffer:通常配合 partial 渲染,按块刷新;
- 双 buffer:常见 ping-pong 模式,一个渲染一个刷屏;
- 三 buffer:在有 GPU/高速总线的平台上进一步解耦渲染与显示,减少等待时间。
这些内容在《画布缓冲管理》与《局部刷新和脏区计算规则》中有详细展开,这里不再重复推导公式,只保留大方向上的关系。
4. _lv_display_t 关键模块总览
本节从 _lv_display_t 的角度,用"模块视角"快速回顾各字段组的职责,并指引到对应子文档。
4.1 分辨率与坐标系统
相关字段:
hor_res/ver_res:逻辑分辨率;physical_hor_res/physical_ver_res:物理/全屏分辨率;offset_x/offset_y:在物理屏上的偏移;dpi:每英寸像素点数。
主要负责:
- 定义 LVGL 逻辑坐标空间;
- 支持多窗口/子区域显示(通过 physical_* + offset_*);
- 为 DPI 相关的布局/组件提供基础信息。
详见:《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-分辨率管理》。
4.2 画布缓冲与 display pipeline
相关字段:
buf_1/buf_2/buf_3/buf_act;_static_buf1/_static_buf2;render_mode/antialiasing/tile_cnt/stride_is_auto;flushing/flushing_last/last_area/last_part;color_format。
主要负责:
- 描述 draw buffer 的数量、大小与当前 active buffer;
- 决定采用何种渲染/刷新策略(partial/full/direct);
- 支持 tile 切分与多 draw unit 并行工作。
详见:《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-画布缓冲管理》与
《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-局部刷新和脏区计算规则》。
4.3 层与屏幕(Layer & Screen)
相关字段:
- Layer 管线:
layer_head/layer_init/layer_deinit; - 屏幕与 UI 基础层:
screens/screen_cnt/act_scr/bottom_layer/top_layer/sys_layer; - 屏幕切换:
prev_scr/scr_to_load/draw_prev_over_act/del_prev。
主要负责:
- 建立从 Layer(像素缓冲合成)到 Screen/Layer 对象(UI 结构)的桥梁;
- 管理普通屏幕、底层背景、顶层覆盖层、系统层的叠加顺序;
- 控制屏幕切换动画及旧屏幕的生命周期。
详见:《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-图层管理》。
4.4 旋转与主题
相关字段:
- 旋转:
rotation/matrix_rotation; - 主题:
lv_theme_t * theme。
主要负责:
- 为显示方向(0/90/180/270)和矩阵旋转提供基础配置;
- 为整套 UI 提供统一的颜色/字体/组件样式入口。
详见:
- 《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-旋转方案》;
- 《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-主题管理》。
4.5 调试与监控
相关字段(在启用监控宏时):
- 性能监控:
perf_label/perf_sysmon_backend/perf_sysmon_info; - 内存监控:
mem_label。
主要负责:
- 提供性能与内存监控的 UI 出口;
- 结合
lv_sysmon.c,在不侵入业务代码的前提下采样刷新/渲染/flush/CPU/内存等关键指标。
详见:《【奶茶Beta专项】【LVGL9.4源码分析】03-显示框架-内存和性能调试》。
5. 与 draw/tick 的调用关系(高层时序)
从时序上看,显示框架与 tick/定时器/draw 模块之间的关系可以概括为:
text
系统 tick:
lv_tick_inc() // 由 SysTick / 定时中断驱动
│
▼
定时器调度:
lv_timer_handler()
│
├─ 调度各种用户/系统定时任务
└─ 定期触发 lv_display_refr_timer(disp)
│
▼
刷新核心 (lv_display_refr_timer / lv_refr.c):
- 处理 inv_areas / sync_areas
- 为每个区域配置 lv_layer_t
- 调用 draw backend (lv_draw_xxx) 渲染到 buf_act
- 调用 flush_cb 把 buffer 推送到物理屏
│
▼
驱动 & 控制器:
- DMA/显示控制器执行实际刷屏
- 完成后调用 lv_display_flush_ready(disp)
在这个链路中:
- tick 层负责"什么时候需要刷新";
- display + lv_refr.c 决定"刷新哪些区域、以什么粒度刷新";
- draw 模块负责"在 buffer 上画什么";
- 驱动负责"如何把 buffer 送到屏幕上"。
6. 移植与调优的整体建议
从整体设计到具体实现,显示框架最容易踩坑的地方集中在以下几点:
-
分辨率/offset/旋转的组合:
- 建议先在无旋转、全屏模式下打通刷新链路,再逐步引入 offset 和旋转;
- 遇到画面"偏一角"或"整体偏移",优先检查 physical_* 与 offset_* 的组合。
-
buffer 尺寸与 render_mode 配合:
- buffer 太小却使用 FULL/DIRECT 容易引发越界或断言;
- 单 buffer + partial 模式下,要关注 tile 切分与脏区合并策略。
-
flush 回调的正确性:
- 保证 flush_cb 在正确的区域范围内写入像素;
- 在双缓冲/三缓冲场景中,注意硬件层面的地址切换是否和 LVGL 的 buffer 切换一致。
-
调试工具的利用:
- 开启性能/内存监控(sysmon)可以极大减少"猜原因"的成本;
- 建议在开发阶段保持 sysmon 支持,在量产固件中根据需求关闭或只保留日志模式。