前面移植了lvgl到全志r528平台(Linux),但是运行起来界面有些卡顿,当遇到页面切换时帧率能下降到个位数。为此,我查阅了大量资料,咨询了方案厂商,总结出一些优化方案。注意这是针对Linux平台下的优化。
根据厂商提供的资料和Demo,我们可以使用全志提供的驱动文件代替lvgl自带的fb驱动。实际效果并不理想,厂商还在优化探索当中。
根据lvgl的资料,我们可以初始化两个缓冲区,采用双缓存来刷新。双缓存也可以增加刷新速度。对于缓存区的大小也有讲究,网络上也有人分析对比过,当采用两个缓冲区,每个缓冲区相当于屏幕的一半大小时效果最佳,但是我们在实践过程中,遇到了一些问题,最终采用了两个和屏幕一样大的缓冲区。
/*Create a display buffer*/
static lv_disp_draw_buf_t disp_buf1;
static lv_color_t buf1_1[HAIER_HOR_RES * HAIER_VER_RES];
static lv_color_t buf1_2[HAIER_HOR_RES * HAIER_VER_RES];
lv_disp_draw_buf_init(&disp_buf1, buf1_1, buf1_2, HAIER_HOR_RES * HAIER_VER_RES);
在显示驱动中有一个参数是是否开启全局刷新,我们把它设置为0即可。以下贴了lv_disp_drv_t的几个配置项,可以根据自己情况进行修改和测试效果,选择适合自己配置参数。
typedef struct _lv_disp_drv_t {
lv_coord_t hor_res; /**< Horizontal resolution.*/
lv_coord_t ver_res; /**< Vertical resolution.*/
lv_coord_t
physical_hor_res; /**< Horizontal resolution of the full / physical display. Set to -1 for fullscreen mode.*/
lv_coord_t
physical_ver_res; /**< Vertical resolution of the full / physical display. Set to -1 for fullscreen mode.*/
lv_coord_t
offset_x; /**< Horizontal offset from the full / physical display. Set to 0 for fullscreen mode.*/
lv_coord_t offset_y; /**< Vertical offset from the full / physical display. Set to 0 for fullscreen mode.*/
/** Pointer to a buffer initialized with `lv_disp_draw_buf_init()`.
* LVGL will use this buffer(s) to draw the screens contents*/
lv_disp_draw_buf_t * draw_buf;
uint32_t direct_mode : 1; /**< 1: Use screen-sized buffers and draw to absolute coordinates*/
uint32_t full_refresh : 1; /**< 1: Always make the whole screen redrawn*/
uint32_t sw_rotate : 1; /**< 1: use software rotation (slower)*/
uint32_t antialiasing : 1; /**< 1: anti-aliasing is enabled on this display.*/
uint32_t rotated : 2; /**< 1: turn the display by 90 degree. @warning Does not update coordinates for you!*/
uint32_t screen_transp : 1; /**Handle if the screen doesn't have a solid (opa == LV_OPA_COVER) background.
* Use only if required because it's slower.*/
uint32_t dpi : 10; /** DPI (dot per inch) of the display. Default value is `LV_DPI_DEF`.*/
........other code ............
} lv_disp_drv_t;
尽量减少图层的叠加,以电台首页为例:
static lv_obj_t *create_obj_radio_home(lv_fragment_t *self, lv_obj_t *container)
{
// 修改前,叠加一个背景图层,实际没有必要,可以优化掉
// lv_obj_t *lv_parent = lv_obj_create_full(container, COLOR_PAGE_BG);
// lv_obj_add_event_cb(lv_parent, event_handler, LV_EVENT_CLICKED, NULL);
// lv_list = lv_obj_create_transp(lv_parent, COLOR_TRANSP);
// 修改后:
lv_list = lv_obj_create_full(container, COLOR_PAGE_BG);
lv_obj_set_style_bg_color(container, lv_color_hex(0x161616), LV_STATE_DEFAULT);
// lv_obj_set_style_bg_opa(lv_list, LV_OPA_TRANSP, LV_STATE_DEFAULT);
lv_obj_set_user_data(lv_list, 9999);
lv_obj_set_size(lv_list, LV_PCT(100), HAIER_SIZE(1048));
lv_obj_set_pos(lv_list, 0, HAIER_SIZE(102));
lv_obj_set_style_bg_color(lv_list, lv_color_hex(0x161616), LV_STATE_DEFAULT);
lv_obj_set_scrollbar_mode(lv_list, LV_SCROLLBAR_MODE_OFF);
......
当文字叠加到图片上方时会引发卡顿。以首页应用列表Tab为例,我们将文案内容固定的文字切为图片,可以大大减少卡顿情况:
static void creat_app_card(lv_obj_t *tab, app_data data)
{
lv_obj_t *app_card = lv_obj_create_transp(tab, COLOR_TRANSP);
lv_obj_set_size(app_card, HAIER_SIZE(140), HAIER_SIZE(185));
lv_obj_add_event_cb(app_card, app_click_handler, LV_EVENT_CLICKED, data.pos);
lv_obj_t *img_bg = lv_img_create_transp(app_card, &icon_app_bg);
lv_obj_set_size(img_bg, HAIER_SIZE(120), HAIER_SIZE(120));
lv_obj_align(img_bg, LV_ALIGN_TOP_MID, 0, HAIER_SIZE(10));
lv_obj_add_event_cb(img_bg, app_click_handler, LV_EVENT_CLICKED, data.pos);
lv_obj_t *img_icon = lv_img_create_transp(img_bg, data.icon);
lv_obj_center(img_icon);
lv_obj_add_event_cb(img_icon, app_click_handler, LV_EVENT_CLICKED, data.pos);
lv_obj_t *name = lv_label_create_transp(app_card, data.name, COLOR_WHITE);
lv_obj_add_style(name, &common_font_style_24_bold, LV_STATE_DEFAULT);
lv_obj_align_to(name, img_bg, LV_ALIGN_OUT_BOTTOM_MID, 0, HAIER_SIZE(23));
lv_obj_add_event_cb(name, app_click_handler, LV_EVENT_CLICKED, data.pos);
}
static void create_app_card_new(lv_obj_t *tab, app_data data){
lv_obj_t *app_card = lv_img_create_transp(tab, app_img_new[data.pos]);
lv_obj_set_size(app_card, HAIER_SIZE(120), HAIER_SIZE(170));
lv_obj_add_event_cb(app_card, app_click_handler, LV_EVENT_CLICKED, data.pos);
}
前面讲过,字体和图片叠加会引起帧数降低,于是分别测试图片和文字,发现引起卡顿的主要是文字。以低置恒温页面和电台首页为例:
页面 | 优化前 | 探索实验 | ||
---|---|---|---|---|
电台首页 | 10fps | 图文叠加,图片居多 | 66fps | 去掉文字 |
恒温首页 | 10fps | 图文交替,文字较多 | 15fps | 去掉图片 |
由以上现象我们可以得出结论,文字会影响帧率,于是找到lv_conf.h文件中关于freetypoe的相关的配置:
加大缓存,更换缓存类型:最终低置恒温,菜谱等这类“图文交替”的页面在全屏滑动时能够稳定在30FPS+,达到了良好的显示效果。
/*FreeType library*/
#define LV_USE_FREETYPE 1
#if LV_USE_FREETYPE
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
#define LV_FREETYPE_CACHE_SIZE (16 * 1024)
#if LV_FREETYPE_CACHE_SIZE >= 0
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
/* if font size >= 256, must be configured as image cache */
#define LV_FREETYPE_SBIT_CACHE 1
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
/* (0:use system defaults) */
#define LV_FREETYPE_CACHE_FT_FACES 1
#define LV_FREETYPE_CACHE_FT_SIZES 20
#endif
#endif
/*FreeType library*/
#define LV_USE_FREETYPE 1
#if LV_USE_FREETYPE
/*Memory used by FreeType to cache characters [bytes] (-1: no caching)*/
#define LV_FREETYPE_CACHE_SIZE (4 * 1024*1024)
#if LV_FREETYPE_CACHE_SIZE >= 0
/* 1: bitmap cache use the sbit cache, 0:bitmap cache use the image cache. */
/* sbit cache:it is much more memory efficient for small bitmaps(font size < 256) */
/* if font size >= 256, must be configured as image cache */
#define LV_FREETYPE_SBIT_CACHE 0
/* Maximum number of opened FT_Face/FT_Size objects managed by this cache instance. */
/* (0:use system defaults) */
#define LV_FREETYPE_CACHE_FT_FACES 20
#define LV_FREETYPE_CACHE_FT_SIZES 30
#endif
#endif