Display

每一个物理显示设备都有一个Display(lv_display)

lvgl初始化一个物理显示设备需要进行以下操作:

  • 为这个物理显示设备创建一个lv_display_t对象,并设置物理设备的宽高
  • 为这个对象提供绘图函数(硬件驱动)
  • 分配draw_buffers。把这个buffer当成lvgl的草稿纸,lvgl写完草稿了,才会写到屏幕上。使用lvgl画图,控件变化等功能,比如填充(0,0,320,240)这个区域lvgl会现在这个buffer中完成绘制,再调用绘图函数将buffer里的数据同步到显示屏。注意:buffer可能很小,比如才320*10,那么这个buffer,需要调用240/10=24次绘图函数
static void init_lvgl_buf(void)
{
  /*Create a display buffer*/
  static lv_disp_draw_buf_t disp_buf1;//定义一个显示绘图缓冲区结构体,用于管理 LVGL 的“草稿纸”。
  static lv_color_t buf1_1[SDL_HOR_RES * 100];//分配一块内存作为缓冲区
  lv_disp_draw_buf_init(&disp_buf1, buf1_1, NULL, SDL_HOR_RES * 100);//初始化缓冲区结构体

  /*创建 lv_disp_drv_t驱动描述符 */
  static lv_disp_drv_t disp_drv;
  lv_disp_drv_init(&disp_drv);
    
  /* 给驱动描述符对象分配内存,设置Display宽高,提供绘图函数*/
  disp_drv.draw_buf = &disp_buf1;
  disp_drv.flush_cb = sdl_display_flush;
  disp_drv.hor_res = SDL_HOR_RES;
  disp_drv.ver_res = SDL_VER_RES;

  /*创建Display对象,会根据前面的驱动描述符对象中的内容创建*/
  lv_disp_t *disp = lv_disp_drv_register(&disp_drv);

}

lv_disp_drv_register做了什么

为什么**lv_scr_act()**能拿到默认显示屏的widgets根节点?

LVGL 中,显示设备通过全局链表默认指针来管理多个显示屏。

  • 全局静态变量:在文件作用域定义链表头(_lv_ll_t)和全局 disp_default 指针,提供模块内部的“上下文”。必然有一个变量存储lv_disp_t
  • 通用链表(_lv_ll_t:LVGL 实现了一个轻量级双向链表,可容纳任意类型的节点,避免为每种对象重写链表操作。
  • 动态内存分配:为每个显示设备分配独立的 lv_disp_t 对象,插入链表后统一管理。
  1. 分配并初始化 lv_disp_t 对象
    • 存储显示驱动参数(分辨率、flush 回调、绘图缓冲区等)。
    • 将该对象挂入全局显示链表,若为第一个显示设备则设为默认显示。
  2. 创建两个屏幕对象(lv_obj_t
    • 活动屏幕(act_scr:当前可见的主屏幕。
    • 上一个屏幕(prev_scr:用于屏幕切换动画的备用屏幕(初始与 act_scr 相同或为 NULL)。
  3. 配置屏幕对象的基本属性
    • 设置屏幕尺寸为显示设备的 hor_res × ver_res
    • 清除可滚动标志(屏幕本身不可滚动)。
    • 标记对象类型为 LV_OBJ_CLASS_SCREEN,使其成为所有其他控件的根容器。
    • 将屏幕的 parent 设为 NULL(顶级对象)。
  4. 将屏幕与显示设备关联
    • disp->act_scr = new_scrdisp->prev_scr = NULL(或 new_scr)。
    • 设置屏幕的 disp 指针指向当前显示设备。
  5. 触发默认主题/样式的加载
    • 如果 LVGL 启用了主题功能,会自动为屏幕应用默认主题(背景色、默认样式等)。
    • 主题可能进一步初始化默认字体、颜色方案等。
  6. 强制刷新整个屏幕(首次重绘)
    • 调用 lv_obj_invalidate(act_scr) 标记整个屏幕为“脏”。
    • 随后 LVGL 的任务调度器会触发一次全屏重绘:在绘图缓冲区中绘制屏幕背景,并通过 flush_cb 发送到物理显示屏。
  7. 使 lv_scr_act() 可用
    • lv_scr_act() 定义为 lv_disp_get_scr_act(lv_disp_get_default()),此时默认显示设备已存在,act_scr 已有效,因此可以返回屏幕根控件指针。