基于lvgl v7.11.0
一、关于硬件加速
LVGL提供了一些GPU的硬件加速接口 lv_hal_disp.h
可以在lv_conf.h 中将宏打开。
相关接口如下:
/** MANDATORY: Write the internal buffer (VDB) to the display. 'lv_disp_flush_ready()' has to be
* called when finished */
void (*flush_cb)(struct _disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
/** OPTIONAL: Extend the invalidated areas to match with the display drivers requirements
* E.g. round `y` to, 8, 16 ..) on a monochrome display*/
void (*rounder_cb)(struct _disp_drv_t * disp_drv, lv_area_t * area);
/** OPTIONAL: Set a pixel in a buffer according to the special requirements of the display
* Can be used for color format not supported in LittelvGL. E.g. 2 bit -> 4 gray scales
* @note Much slower then drawing with supported color formats. */
void (*set_px_cb)(struct _disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
lv_color_t color, lv_opa_t opa);
/** OPTIONAL: Called after every refresh cycle to tell the rendering and flushing time + the
* number of flushed pixels */
void (*monitor_cb)(struct _disp_drv_t * disp_drv, uint32_t time, uint32_t px);
/** OPTIONAL: Called periodically while lvgl waits for operation to be completed.
* For example flushing or GPU
* User can execute very simple tasks here or yield the task */
void (*wait_cb)(struct _disp_drv_t * disp_drv);
/** OPTIONAL: Called when lvgl needs any CPU cache that affects rendering to be cleaned */
void (*clean_dcache_cb)(struct _disp_drv_t * disp_drv);
/** OPTIONAL: called to wait while the gpu is working */
void (*gpu_wait_cb)(struct _disp_drv_t * disp_drv);
#if LV_USE_GPU
/** OPTIONAL: Blend two memories using opacity (GPU only)*/
void (*gpu_blend_cb)(struct _disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length,
lv_opa_t opa);
/** OPTIONAL: Fill a memory with a color (GPU only)*/
void (*gpu_fill_cb)(struct _disp_drv_t * disp_drv, lv_color_t * dest_buf, lv_coord_t dest_width,
const lv_area_t * fill_area, lv_color_t color);
#endif
flush_cb 双framebuffer切换
gpu_fill_cb 区域色彩填充
gpu_blend_cb 区域 alpha 操作
所以就是说你要实现cpu自带的硬件加速比如海思的tde等需要自己实现上述的接口。可以参考在lv_port_disp.c 中实现。
二、关于双framebuffer
fb一般都有双buffer的机制,用于前台显示后台绘制,当后台绘制完成后lcd控制器切换到后台buffer显示,这样绘制过程就不会让界面显示出现撕裂及闪烁的情况。
lvgl提供了双buffer的模式。lv_port_disp.c
void lv_port_disp_init(void)
/* 3. Create TWO screen-sized buffer:
* Similar to 2) but the buffer have to be screen sized. When LVGL is ready it will give the
* whole frame to display. This way you only need to change the frame buffer's address instead of
* copying the pixels.
* */
/* Example for 3) */
static lv_disp_buf_t draw_buf_dsc_3;
static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*A screen sized buffer*/
static lv_color_t draw_buf_3_2[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*An other screen sized buffer*/
lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/
disp_drv.buffer = &draw_buf_dsc_3;
disp_drv.flush_cb = disp_flush; //注册硬件加速函数
#if LV_USE_GPU
/*Optionally add functions to access the GPU. (Only in buffered mode, LV_VDB_SIZE != 0)*/
/*Blend two color array using opacity*/
disp_drv.gpu_blend_cb = gpu_blend;
/*Fill a memory array with a color*/
disp_drv.gpu_fill_cb = gpu_fill;
#endif
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
注意注释部分
lvgl在拿到这两个buffer的时候会在后台的buffer上直接绘制,等待绘制成功后再切换buffer,切换动作在flush_cb 上完成,然后再同步前后台更新的内容,保存两个buffer间的图像同步。lvgl的绘制流程是上述这样,v8.0换了一种绘制模式,就是小区域的ui更新将引发整个screen的更新也就是每次都绘制整个界面的obj,所以这时候就不用做双buffer间的图像同步了。
这两种刷新方式我觉得还是第一中比较方便。因为做图像同步的过程可以加入硬件加速。这样整体流程会快很多。相较于第二种更新方式,每次都是刷整个screen耗时较多且没有地方能加入加速。
关于v8.0注意在移植的时候如果你开了双buffer的模式记得使能disp_drv.full_refresh = 1.