lvgl/port: optimize fbdev buffer sync algorithm

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
pengyiqiang 2023-02-27 14:36:43 +08:00 committed by Xiang Xiao
parent 8160dd0d56
commit ca403ffaf7

View File

@ -79,11 +79,12 @@ struct fbdev_obj_s
* Private Functions
****************************************************************************/
#if defined(CONFIG_FB_UPDATE)
/****************************************************************************
* Name: buf_rotate_copy
* Name: fbdev_update_area
****************************************************************************/
#if defined(CONFIG_FB_UPDATE)
static void fbdev_update_area(FAR struct fbdev_obj_s *fbdev_obj,
FAR const lv_area_t *area_p)
{
@ -104,43 +105,6 @@ static void fbdev_update_area(FAR struct fbdev_obj_s *fbdev_obj,
}
#endif
/****************************************************************************
* Name: fbdev_copy_areas
****************************************************************************/
static void fbdev_copy_areas(FAR lv_color_t *fb_dest,
FAR const lv_color_t *fb_src,
FAR const lv_area_t *areas,
uint16_t len,
int fb_width)
{
int i;
LV_LOG_TRACE("%p -> %p, len = %d", fb_src, fb_dest, len);
for (i = 0; i < len; i++)
{
int y;
FAR const lv_area_t *area = &(areas[i]);
int width = lv_area_get_width(area);
int height = lv_area_get_height(area);
FAR lv_color_t *dest_pos =
fb_dest + area->y1 * fb_width + area->x1;
FAR const lv_color_t *src_pos =
fb_src + area->y1 * fb_width + area->x1;
size_t hor_size = width * sizeof(lv_color_t);
LV_LOG_TRACE("area[%d]: (%d, %d) %d x %d",
i, area->x1, area->y1, width, height);
for (y = 0; y < height; y++)
{
lv_memcpy(dest_pos, src_pos, hor_size);
dest_pos += fb_width;
src_pos += fb_width;
}
}
}
/****************************************************************************
* Name: fbdev_switch_buffer
****************************************************************************/
@ -227,6 +191,39 @@ static void fbdev_disp_vsync_refr(FAR lv_timer_t *timer)
#endif /* CONFIG_FB_SYNC */
/****************************************************************************
* Name: fbdev_check_inv_area_covered
****************************************************************************/
static bool fbdev_check_inv_area_covered(FAR lv_disp_t *disp_refr,
FAR const lv_area_t *area_p)
{
int i;
for (i = 0; i < disp_refr->inv_p; i++)
{
FAR const lv_area_t *cur_area;
/* Skip joined area */
if (disp_refr->inv_area_joined[i])
{
continue;
}
cur_area = &disp_refr->inv_areas[i];
/* Check cur_area is coverd area_p */
if (_lv_area_is_in(area_p, cur_area, 0))
{
return true;
}
}
return false;
}
/****************************************************************************
* Name: fbdev_render_start
****************************************************************************/
@ -235,45 +232,50 @@ static void fbdev_render_start(FAR lv_disp_drv_t *disp_drv)
{
FAR struct fbdev_obj_s *fbdev_obj = disp_drv->user_data;
FAR lv_disp_t *disp_refr;
FAR lv_draw_ctx_t *draw_ctx;
lv_coord_t hor_res;
lv_coord_t ver_res;
int i;
/* No need sync buffer when inv_areas_len == 0 */
if (fbdev_obj->inv_areas_len == 0)
{
LV_LOG_TRACE("No sync area");
return;
}
LV_LOG_TRACE("Start sync %d areas...", fbdev_obj->inv_areas_len);
disp_refr = _lv_refr_get_disp_refreshing();
draw_ctx = disp_drv->draw_ctx;
hor_res = disp_drv->hor_res;
ver_res = disp_drv->ver_res;
for (i = 0; i < disp_refr->inv_p; i++)
for (i = 0; i < fbdev_obj->inv_areas_len; i++)
{
if (disp_refr->inv_area_joined[i] == 0)
FAR const lv_area_t *last_area = &fbdev_obj->inv_areas[i];
LV_LOG_TRACE("Check area[%d]: (%d, %d) %d x %d",
i,
(int)last_area->x1, (int)last_area->y1,
(int)lv_area_get_width(last_area),
(int)lv_area_get_height(last_area));
if (fbdev_check_inv_area_covered(disp_refr, last_area))
{
FAR const lv_area_t *area_p = &disp_refr->inv_areas[i];
/* If a full screen redraw is detected, skip dirty areas sync */
if (lv_area_get_width(area_p) == hor_res
&& lv_area_get_height(area_p) == ver_res)
{
LV_LOG_TRACE("Full screen redraw, skip dirty areas sync");
fbdev_obj->inv_areas_len = 0;
return;
}
LV_LOG_TRACE("Skipped");
continue;
}
/* Sync the inv area of the previous frame */
draw_ctx->buffer_copy(
draw_ctx,
fbdev_obj->act_buffer, hor_res, last_area,
fbdev_obj->last_buffer, hor_res, last_area);
LV_LOG_TRACE("Copied");
}
/* Sync the dirty area of the previous frame */
fbdev_copy_areas(fbdev_obj->act_buffer, fbdev_obj->last_buffer,
fbdev_obj->inv_areas, fbdev_obj->inv_areas_len,
fbdev_obj->vinfo.xres);
fbdev_obj->inv_areas_len = 0;
}