lvgl/port: optimize fbdev buffer sync algorithm
Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
parent
8160dd0d56
commit
ca403ffaf7
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user