Skip to content

Commit

Permalink
perf(vg_lite): improve path append data performance (lvgl#7504)
Browse files Browse the repository at this point in the history
Signed-off-by: pengyiqiang <[email protected]>
Co-authored-by: pengyiqiang <[email protected]>
  • Loading branch information
FASTSHIFT and pengyiqiang authored Dec 24, 2024
1 parent bd39f98 commit f378299
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 46 deletions.
12 changes: 5 additions & 7 deletions src/draw/vg_lite/lv_draw_vg_lite_vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -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); \
Expand All @@ -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:
Expand Down
98 changes: 69 additions & 29 deletions src/draw/vg_lite/lv_vg_lite_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
**********************/
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand All @@ -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);
Expand All @@ -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;
}

Expand Down
13 changes: 7 additions & 6 deletions src/draw/vg_lite/lv_vg_lite_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
**********************/
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions src/draw/vg_lite/lv_vg_lite_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
2 changes: 0 additions & 2 deletions src/draw/vg_lite/lv_vg_lite_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit f378299

Please sign in to comment.