From f3782993702b0bc8e9b21e078cc2871cf05d4950 Mon Sep 17 00:00:00 2001 From: VIFEX Date: Tue, 24 Dec 2024 18:48:36 +0800 Subject: [PATCH] perf(vg_lite): improve path append data performance (#7504) Signed-off-by: pengyiqiang Co-authored-by: pengyiqiang --- src/draw/vg_lite/lv_draw_vg_lite_vector.c | 12 ++- src/draw/vg_lite/lv_vg_lite_path.c | 98 ++++++++++++++++------- src/draw/vg_lite/lv_vg_lite_path.h | 13 +-- src/draw/vg_lite/lv_vg_lite_utils.c | 4 +- src/draw/vg_lite/lv_vg_lite_utils.h | 2 - 5 files changed, 83 insertions(+), 46 deletions(-) diff --git a/src/draw/vg_lite/lv_draw_vg_lite_vector.c b/src/draw/vg_lite/lv_draw_vg_lite_vector.c index 156bed416..130cc7235 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_vector.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_vector.c @@ -346,8 +346,6 @@ static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src if((point)->y > max_y) max_y = (point)->y; \ } while(0) -#define VLC_SET_OP_CODE(ptr, op) (*((uint32_t*)ptr) = (op)) - #define COPY_POINT_NEXT() \ do { \ CMP_BOUNDS(point); \ @@ -371,30 +369,30 @@ static void lv_path_to_vg(lv_vg_lite_path_t * dest, const lv_vector_path_t * src for(uint32_t i = 0; i < op_size; i++) { switch(ops[i]) { case LV_VECTOR_PATH_OP_MOVE_TO: { - VLC_SET_OP_CODE(path_data++, VLC_OP_MOVE); + LV_VG_LITE_PATH_SET_OP_CODE(path_data++, uint32_t, VLC_OP_MOVE); COPY_POINT_NEXT(); } break; case LV_VECTOR_PATH_OP_LINE_TO: { - VLC_SET_OP_CODE(path_data++, VLC_OP_LINE); + LV_VG_LITE_PATH_SET_OP_CODE(path_data++, uint32_t, VLC_OP_LINE); COPY_POINT_NEXT(); } break; case LV_VECTOR_PATH_OP_QUAD_TO: { - VLC_SET_OP_CODE(path_data++, VLC_OP_QUAD); + LV_VG_LITE_PATH_SET_OP_CODE(path_data++, uint32_t, VLC_OP_QUAD); COPY_POINT_NEXT(); COPY_POINT_NEXT(); } break; case LV_VECTOR_PATH_OP_CUBIC_TO: { - VLC_SET_OP_CODE(path_data++, VLC_OP_CUBIC); + LV_VG_LITE_PATH_SET_OP_CODE(path_data++, uint32_t, VLC_OP_CUBIC); COPY_POINT_NEXT(); COPY_POINT_NEXT(); COPY_POINT_NEXT(); } break; case LV_VECTOR_PATH_OP_CLOSE: { - VLC_SET_OP_CODE(path_data++, VLC_OP_CLOSE); + LV_VG_LITE_PATH_SET_OP_CODE(path_data++, uint32_t, VLC_OP_CLOSE); } break; default: diff --git a/src/draw/vg_lite/lv_vg_lite_path.c b/src/draw/vg_lite/lv_vg_lite_path.c index 13b944966..450b49ad8 100644 --- a/src/draw/vg_lite/lv_vg_lite_path.c +++ b/src/draw/vg_lite/lv_vg_lite_path.c @@ -32,6 +32,9 @@ case VLC_OP_##OP: \ return (LEN) +#define PATH_CURRENT_PTR(PATH) ((uint8_t*)(PATH)->base.path + (PATH)->base.path_length) +#define PATH_LENGTH_INC(PATH, LENGTH) ((PATH)->base.path_length += (LENGTH)) + /********************** * TYPEDEFS **********************/ @@ -279,21 +282,39 @@ void lv_vg_lite_path_reserve_space(lv_vg_lite_path_t * path, size_t len) LV_ASSERT_MALLOC(path->base.path); } -void lv_vg_lite_path_append_data(lv_vg_lite_path_t * path, const void * data, size_t len) +static inline void lv_vg_lite_path_append_data(lv_vg_lite_path_t * path, const void * data, size_t len) { LV_ASSERT_NULL(path); LV_ASSERT_NULL(data); lv_vg_lite_path_reserve_space(path, len); - lv_memcpy((uint8_t *)path->base.path + path->base.path_length, data, len); - path->base.path_length += len; + lv_memcpy(PATH_CURRENT_PTR(path), data, len); + PATH_LENGTH_INC(path, len); } -static void lv_vg_lite_path_append_op(lv_vg_lite_path_t * path, uint32_t op) +static inline void lv_vg_lite_path_append_op(lv_vg_lite_path_t * path, uint32_t op) { - lv_vg_lite_path_append_data(path, &op, path->format_len); + void * ptr = PATH_CURRENT_PTR(path); + switch(path->base.format) { + case VG_LITE_FP32: + case VG_LITE_S32: + LV_VG_LITE_PATH_SET_OP_CODE(ptr, uint32_t, op); + PATH_LENGTH_INC(path, sizeof(uint32_t)); + break; + case VG_LITE_S16: + LV_VG_LITE_PATH_SET_OP_CODE(ptr, uint16_t, op); + PATH_LENGTH_INC(path, sizeof(uint16_t)); + break; + case VG_LITE_S8: + LV_VG_LITE_PATH_SET_OP_CODE(ptr, uint8_t, op); + PATH_LENGTH_INC(path, sizeof(uint8_t)); + break; + default: + LV_ASSERT_FORMAT_MSG(false, "Invalid format: %d", path->base.format); + break; + } } -static void lv_vg_lite_path_append_point(lv_vg_lite_path_t * path, float x, float y) +static inline void lv_vg_lite_path_append_point(lv_vg_lite_path_t * path, float x, float y) { if(path->has_transform) { LV_VG_LITE_ASSERT_MATRIX(&path->matrix); @@ -304,22 +325,39 @@ static void lv_vg_lite_path_append_point(lv_vg_lite_path_t * path, float x, floa y = ori_x * path->matrix.m[1][0] + ori_y * path->matrix.m[1][1] + path->matrix.m[1][2]; } - if(path->base.format == VG_LITE_FP32) { - lv_vg_lite_path_append_data(path, &x, sizeof(x)); - lv_vg_lite_path_append_data(path, &y, sizeof(y)); - return; - } +#define PATH_APPEND_POINT_DATA(X, Y, TYPE) \ + do { \ + TYPE * data = ptr; \ + *data++ = (TYPE)(X); \ + *data++ = (TYPE)(Y); \ + PATH_LENGTH_INC(path, sizeof(TYPE) * 2); \ + } while(0) - int32_t ix = (int32_t)(x); - int32_t iy = (int32_t)(y); - lv_vg_lite_path_append_data(path, &ix, path->format_len); - lv_vg_lite_path_append_data(path, &iy, path->format_len); + void * ptr = PATH_CURRENT_PTR(path); + switch(path->base.format) { + case VG_LITE_FP32: + PATH_APPEND_POINT_DATA(x, y, float); + break; + case VG_LITE_S32: + PATH_APPEND_POINT_DATA(x, y, int32_t); + break; + case VG_LITE_S16: + PATH_APPEND_POINT_DATA(x, y, int16_t); + break; + case VG_LITE_S8: + PATH_APPEND_POINT_DATA(x, y, int8_t); + break; + default: + LV_ASSERT_FORMAT_MSG(false, "Invalid format: %d", path->base.format); + break; + } } void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path, float x, float y) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, (1 + 2) * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_MOVE); lv_vg_lite_path_append_point(path, x, y); } @@ -328,6 +366,7 @@ void lv_vg_lite_path_line_to(lv_vg_lite_path_t * path, float x, float y) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, (1 + 2) * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_LINE); lv_vg_lite_path_append_point(path, x, y); } @@ -337,6 +376,7 @@ void lv_vg_lite_path_quad_to(lv_vg_lite_path_t * path, float x, float y) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, (1 + 4) * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_QUAD); lv_vg_lite_path_append_point(path, cx, cy); lv_vg_lite_path_append_point(path, x, y); @@ -348,6 +388,7 @@ void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path, float x, float y) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, (1 + 6) * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_CUBIC); lv_vg_lite_path_append_point(path, cx1, cy1); lv_vg_lite_path_append_point(path, cx2, cy2); @@ -357,12 +398,14 @@ void lv_vg_lite_path_cubic_to(lv_vg_lite_path_t * path, void lv_vg_lite_path_close(lv_vg_lite_path_t * path) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, 1 * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_CLOSE); } void lv_vg_lite_path_end(lv_vg_lite_path_t * path) { LV_ASSERT_NULL(path); + lv_vg_lite_path_reserve_space(path, 1 * path->format_len); lv_vg_lite_path_append_op(path, VLC_OP_END); path->base.add_end = 1; } @@ -570,31 +613,29 @@ uint8_t lv_vg_lite_vlc_op_arg_len(uint8_t vlc_op) VLC_OP_ARG_LEN(LCWARC, 5); VLC_OP_ARG_LEN(LCWARC_REL, 5); default: + LV_ASSERT_FORMAT_MSG(false, "Invalid op code: %d", vlc_op); break; } - LV_LOG_ERROR("UNKNOW_VLC_OP: 0x%x", vlc_op); - LV_ASSERT(false); return 0; } uint8_t lv_vg_lite_path_format_len(vg_lite_format_t format) { switch(format) { - case VG_LITE_S8: - return 1; - case VG_LITE_S16: - return 2; - case VG_LITE_S32: - return 4; case VG_LITE_FP32: - return 4; + return sizeof(float); + case VG_LITE_S32: + return sizeof(int32_t); + case VG_LITE_S16: + return sizeof(int16_t); + case VG_LITE_S8: + return sizeof(int8_t); default: + LV_ASSERT_FORMAT_MSG(false, "Invalid format: %d", format); break; } - LV_LOG_ERROR("UNKNOW_FORMAT: %d", format); - LV_ASSERT(false); return 0; } @@ -610,7 +651,7 @@ void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_ while(cur < end) { /* get op code */ - uint8_t op_code = VLC_GET_OP_CODE(cur); + uint8_t op_code = LV_VG_LITE_PATH_GET_OP_CODE(cur); /* get arguments length */ uint8_t arg_len = lv_vg_lite_vlc_op_arg_len(op_code); @@ -634,8 +675,7 @@ void lv_vg_lite_path_for_each_data(const vg_lite_path_t * path, lv_vg_lite_path_ tmp_data[i] = *((float *)cur); break; default: - LV_LOG_ERROR("UNKNOW_FORMAT(%d)", path->format); - LV_ASSERT(false); + LV_ASSERT_FORMAT_MSG(false, "Invalid format: %d", path->format); break; } diff --git a/src/draw/vg_lite/lv_vg_lite_path.h b/src/draw/vg_lite/lv_vg_lite_path.h index b18d19c75..e9d762919 100644 --- a/src/draw/vg_lite/lv_vg_lite_path.h +++ b/src/draw/vg_lite/lv_vg_lite_path.h @@ -22,15 +22,18 @@ extern "C" { * DEFINES *********************/ -typedef struct _lv_vg_lite_path_t lv_vg_lite_path_t; -typedef struct _lv_draw_vg_lite_unit_t lv_draw_vg_lite_unit_t; - -typedef void (*lv_vg_lite_path_iter_cb_t)(void * user_data, uint8_t op_code, const float * data, uint32_t len); +#define LV_VG_LITE_PATH_SET_OP_CODE(PTR, TYPE, OP_CODE) (*((TYPE*)PTR) = (OP_CODE)) +#define LV_VG_LITE_PATH_GET_OP_CODE(PTR) (*((uint8_t*)PTR)) /********************** * TYPEDEFS **********************/ +typedef struct _lv_vg_lite_path_t lv_vg_lite_path_t; +typedef struct _lv_draw_vg_lite_unit_t lv_draw_vg_lite_unit_t; + +typedef void (*lv_vg_lite_path_iter_cb_t)(void * user_data, uint8_t op_code, const float * data, uint32_t len); + /********************** * GLOBAL PROTOTYPES **********************/ @@ -69,8 +72,6 @@ vg_lite_path_t * lv_vg_lite_path_get_path(lv_vg_lite_path_t * path); void lv_vg_lite_path_reserve_space(lv_vg_lite_path_t * path, size_t len); -void lv_vg_lite_path_append_data(lv_vg_lite_path_t * path, const void * data, size_t len); - void lv_vg_lite_path_move_to(lv_vg_lite_path_t * path, float x, float y); diff --git a/src/draw/vg_lite/lv_vg_lite_utils.c b/src/draw/vg_lite/lv_vg_lite_utils.c index eb48fe8a7..cada4e745 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.c +++ b/src/draw/vg_lite/lv_vg_lite_utils.c @@ -1052,7 +1052,7 @@ bool lv_vg_lite_path_check(const vg_lite_path_t * path) while(cur < end) { /* get op code */ - uint8_t op_code = VLC_GET_OP_CODE(cur); + uint8_t op_code = LV_VG_LITE_PATH_GET_OP_CODE(cur); /* get arguments length */ uint8_t arg_len = lv_vg_lite_vlc_op_arg_len(op_code); @@ -1076,7 +1076,7 @@ bool lv_vg_lite_path_check(const vg_lite_path_t * path) case VG_LITE_DRAW_FILL_PATH: case VG_LITE_DRAW_FILL_STROKE_PATH: { /* Check end op code */ - uint8_t end_op_code = VLC_GET_OP_CODE(end - fmt_len); + uint8_t end_op_code = LV_VG_LITE_PATH_GET_OP_CODE(end - fmt_len); if(end_op_code != VLC_OP_END) { LV_LOG_ERROR("%d (%s) -> is NOT VLC_OP_END", end_op_code, lv_vg_lite_vlc_op_string(end_op_code)); return false; diff --git a/src/draw/vg_lite/lv_vg_lite_utils.h b/src/draw/vg_lite/lv_vg_lite_utils.h index 3a6ebd038..2871cfcee 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.h +++ b/src/draw/vg_lite/lv_vg_lite_utils.h @@ -33,8 +33,6 @@ extern "C" { #define LV_VG_LITE_IS_ERROR(err) (err > 0) -#define VLC_GET_OP_CODE(ptr) (*((uint8_t*)ptr)) - #if LV_VG_LITE_USE_ASSERT #define LV_VG_LITE_ASSERT(expr) LV_ASSERT(expr) #else