/* 定义TDE绘图上下文结构体 */
typedef struct {
lv_draw_ctx_t base;
TDE_HANDLE tde_handle;
TDE2_SURFACE_S dst_surface;
TDE2_OPT_S tde_opt;
} lv_draw_tde_ctx_t;
/*-----------------------------
* 清除屏幕(Clear)
*---------------------------*/
static void lv_tde_clear(lv_draw_ctx_t *draw_ctx, const lv_area_t *area)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
TDE_HANDLE handle = HI_TDE2_BeginJob();
if (handle == HI_ERR_TDE_INVALID_HANDLE) return;
/* 将整个区域填充为背景色(通常为透明黑) */
TDE2_RECT_S clear_rect = {
.s32Xpos = area->x1,
.s32Ypos = area->y1,
.u32Width = lv_area_get_width(area),
.u32Height = lv_area_get_height(area)
};
TDE2_FILLCOLOR_S clear_color = {
.enColorFmt = TDE2_COLOR_FMT_ARGB8888,
.u32FillColor = 0x00000000 // ARGB8888 格式的透明黑
};
HI_S32 ret = HI_TDE2_QuickFill(handle, &tde_ctx->dst_surface, &clear_rect,
&clear_color, &tde_ctx->tde_opt);
if (ret == HI_SUCCESS) {
HI_TDE2_EndJob(handle, HI_FALSE, HI_TRUE, 100); // 同步等待
}
}
/*-----------------------------
* 混合操作(Blend)
*---------------------------*/
static void lv_tde_blend(lv_draw_ctx_t *draw_ctx, const lv_draw_sw_blend_dsc_t *dsc)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
TDE_HANDLE handle = HI_TDE2_BeginJob();
if (handle == HI_ERR_TDE_INVALID_HANDLE) return;
/* 配置源表面 */
TDE2_SURFACE_S src_surface = {
.enColorFmt = TDE2_COLOR_FMT_ARGB8888,
.u32PhyAddr = (HI_U64)dsc->src_buf,
.u32Width = dsc->src_w,
.u32Height = dsc->src_h,
.u32Stride = dsc->src_stride * lv_color_format_get_size(tde_ctx->cf)
};
/* 定义混合区域 */
TDE2_RECT_S src_rect = {
.s32Xpos = dsc->src_area->x1,
.s32Ypos = dsc->src_area->y1,
.u32Width = lv_area_get_width(dsc->src_area),
.u32Height = lv_area_get_height(dsc->src_area)
};
TDE2_RECT_S dst_rect = {
.s32Xpos = dsc->dest_area->x1,
.s32Ypos = dsc->dest_area->y1,
.u32Width = lv_area_get_width(dsc->dest_area),
.u32Height = lv_area_get_height(dsc->dest_area)
};
/* 配置混合模式 */
TDE2_OPT_S opt = tde_ctx->tde_opt;
opt.enAluCmd = (dsc->blend_mode == LV_BLEND_MODE_ADDITIVE) ?
TDE2_ALUCMD_ADD : TDE2_ALUCMD_SRCOVER;
opt.u8GlobalAlpha = dsc->opa;
/* 执行混合操作 */
HI_S32 ret = HI_TDE2_Bitblit(handle,
&src_surface, &src_rect,
&tde_ctx->dst_surface, &dst_rect,
&opt);
if (ret == HI_SUCCESS) {
HI_TDE2_EndJob(handle, HI_FALSE, HI_TRUE, 100);
}
}
/*-----------------------------
* 图像绘制(Draw Image)
*---------------------------*/
static void lv_tde_draw_img(lv_draw_ctx_t *draw_ctx, const lv_draw_img_dsc_t *dsc,
const lv_area_t *coords, const uint8_t *src_buf)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
TDE_HANDLE handle = HI_TDE2_BeginJob();
if (handle == HI_ERR_TDE_INVALID_HANDLE) return;
/* 配置源图像表面 */
TDE2_SURFACE_S src_surface = {
.enColorFmt = TDE2_COLOR_FMT_ARGB8888, // 假设源为ARGB8888
.u32PhyAddr = (HI_U64)src_buf,
.u32Width = lv_area_get_width(coords),
.u32Height = lv_area_get_height(coords),
.u32Stride = lv_area_get_width(coords) * 4
};
/* 目标区域 */
TDE2_RECT_S dst_rect = {
.s32Xpos = coords->x1,
.s32Ypos = coords->y1,
.u32Width = lv_area_get_width(coords),
.u32Height = lv_area_get_height(coords)
};
/* 处理旋转/缩放 */
if (dsc->angle || dsc->zoom != LV_IMG_ZOOM_NONE) {
TDE2_ROTATE_ANGLE_E rotate = TDE2_ROTATE_NONE;
if (dsc->angle == 900) rotate = TDE2_ROTATE_90;
else if (dsc->angle == 1800) rotate = TDE2_ROTATE_180;
else if (dsc->angle == 2700) rotate = TDE2_ROTATE_270;
HI_TDE2_Rotate(handle, &src_surface, NULL,
&tde_ctx->dst_surface, &dst_rect,
rotate, TDE2_MIRROR_NONE);
}
else {
/* 直接拷贝图像 */
HI_TDE2_QuickCopy(handle,
&src_surface, NULL,
&tde_ctx->dst_surface, &dst_rect,
&tde_ctx->tde_opt);
}
HI_TDE2_EndJob(handle, HI_FALSE, HI_TRUE, 100);
}
/* 颜色格式转换函数(示例) */
static inline HI_U32 lv_color_to_tde_format(lv_color_t color, lv_opa_t opa)
{
return (opa << 24) | (color.red << 16) | (color.green << 8) | color.blue;
}
/* 绘图上下文初始化 */
void lv_draw_tde_ctx_init(lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
/* 初始化基础上下文 */
lv_draw_sw_init_ctx(drv, draw_ctx);
/* 配置TDE目标表面 */
tde_ctx->dst_surface.PhyAddr = (HI_U64)drv->draw_buf->buf_act;
tde_ctx->dst_surface.enColorFmt = TDE2_COLOR_FMT_ARGB8888; // 根据LVGL配置调整
tde_ctx->dst_surface.u32Width = drv->hor_res;
tde_ctx->dst_surface.u32Height = drv->ver_res;
tde_ctx->dst_surface.u32Stride = drv->hor_res * 4; // ARGB8888 stride
/* 初始化TDE默认选项 */
memset(&tde_ctx->tde_opt, 0, sizeof(TDE2_OPT_S));
tde_ctx->tde_opt.enClipMode = TDE2_CLIPMODE_NONE;
tde_ctx->tde_opt.enAluCmd = TDE2_ALUCMD_SRCOVER;
/* 重写绘图函数指针 */
draw_ctx->clear = lv_tde_clear;
draw_ctx->fill = lv_tde_fill;
draw_ctx->blend = lv_tde_blend;
draw_ctx->base_draw.draw_img = lv_tde_draw_img;
}
/* 绘图上下文反初始化 */
void lv_draw_tde_ctx_deinit(lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
/* 取消未完成的任务 */
if (tde_ctx->tde_handle != HI_ERR_TDE_INVALID_HANDLE) {
HI_TDE2_CancelJob(tde_ctx->tde_handle);
}
/* 释放资源 */
lv_draw_sw_deinit_ctx(drv, draw_ctx);
}
/* 填充矩形示例实现 */
static void lv_tde_fill(lv_draw_ctx_t *draw_ctx, const lv_area_t *area, lv_color_t color, lv_opa_t opa)
{
lv_draw_tde_ctx_t *tde_ctx = (lv_draw_tde_ctx_t *)draw_ctx;
/* 创建TDE任务 */
TDE_HANDLE handle = HI_TDE2_BeginJob();
if (handle == HI_ERR_TDE_INVALID_HANDLE) return;
/* 配置填充参数 */
TDE2_RECT_S fill_area = {
.s32Xpos = area->x1,
.s32Ypos = area->y1,
.u32Width = lv_area_get_width(area),
.u32Height = lv_area_get_height(area)
};
TDE2_FILLCOLOR_S fill_color = {
.enColorFmt = TDE2_COLOR_FMT_ARGB8888,
.u32FillColor = lv_color_to32(color) | (opa << 24)
};
/* 执行快速填充 */
HI_S32 ret = HI_TDE2_QuickFill(handle, &tde_ctx->dst_surface, &fill_area,
&fill_color, &tde_ctx->tde_opt);
if (ret == HI_SUCCESS) {
HI_TDE2_EndJob(handle, HI_FALSE, HI_TRUE, 100); // 阻塞等待100ms
}
}
static TDE2_ALUCMD_E blend_mode_map(lv_blend_mode_t mode) {
switch(mode) {
case LV_BLEND_MODE_ADDITIVE: return TDE2_ALUCMD_ADD;
case LV_BLEND_MODE_SUBTRACTIVE: return TDE2_ALUCMD_SUB;
default: return TDE2_ALUCMD_SRCOVER;
}
}
/* 驱动初始化适配 */
void lv_disp_drv_init(lv_disp_drv_t *driver)
{
lv_memset_00(driver, sizeof(lv_disp_drv_t));
driver->hor_res = 720;
driver->ver_res = 1280;
/* 配置TDE绘图上下文 */
driver->draw_ctx_init = lv_draw_tde_ctx_init;
driver->draw_ctx_deinit = lv_draw_tde_ctx_deinit;
driver->draw_ctx_size = sizeof(lv_draw_tde_ctx_t);
/* 其他驱动配置... */
}
/* 批量提交任务(示例) */
void flush_cb(lv_disp_drv_t *drv, const lv_area_t *area) {
lv_draw_tde_ctx_t *ctx = (lv_draw_tde_ctx_t *)drv->draw_ctx;
HI_TDE2_WaitAllDone(ctx->tde_handle); // 确保所有任务完成
lv_disp_flush_ready(drv); // 通知 LVGL 刷新完成
}
进一步分析各函数的执行策略,采用硬件加速前后的数据
perf_monitor.h
/* perf_monitor.h */
#ifndef __PERF_MONITOR_H__
#define __PERF_MONITOR_H__
#include <stdint.h>
#include "lvgl/lvgl.h"
typedef struct {
uint32_t call_count; // 调用次数
uint32_t total_time_us; // 总耗时(微秒)
uint32_t max_time_us; // 单次最大耗时
} func_stats_t;
// 被监控的函数指针类型(适配 LVGL 绘图函数)
typedef void (*draw_func_t)(void *ctx, void *dsc, void *coords_or_points);
// 注册被监控的函数
void perf_monitor_register_func(draw_func_t func_ptr, const char *name);
// 打印统计结果
void perf_monitor_print_stats(void);
// 包装宏(简化函数替换)
#define WRAP_FUNC(orig_func, wrapper_func) \
do { \
perf_monitor_register_func((draw_func_t)orig_func, #orig_func); \
orig_func = (typeof(orig_func))wrapper_func; \
} while(0)
#endif // __PERF_MONITOR_H__
perf_monitor.c
/* 在绘图上下文初始化代码中替换原始函数 */
#include "perf_monitor.h"
/* perf_monitor.c */
#include "perf_monitor.h"
#include <stdio.h>
#define MAX_MONITORED_FUNCS 16
typedef struct {
draw_func_t func_ptr;
func_stats_t stats;
const char *name;
} monitored_func_t;
static monitored_func_t monitored_funcs[MAX_MONITORED_FUNCS];
static uint8_t func_count = 0;
void perf_monitor_register_func(draw_func_t func_ptr, const char *name) {
if (func_count >= MAX_MONITORED_FUNCS) return;
monitored_funcs[func_count].func_ptr = func_ptr;
monitored_funcs[func_count].name = name;
lv_memset_00(&monitored_funcs[func_count].stats, sizeof(func_stats_t));
func_count++;
}
static void update_stats(draw_func_t func_ptr, uint32_t time_us) {
for (int i = 0; i < func_count; i++) {
if (monitored_funcs[i].func_ptr == func_ptr) {
monitored_funcs[i].stats.call_count++;
monitored_funcs[i].stats.total_time_us += time_us;
if (time_us > monitored_funcs[i].stats.max_time_us) {
monitored_funcs[i].stats.max_time_us = time_us;
}
break;
}
}
}
void perf_monitor_print_stats(void) {
printf("\n----- LVGL Draw Function Statistics -----\n");
for (int i = 0; i < func_count; i++) {
func_stats_t *s = &monitored_funcs[i].stats;
if (s->call_count == 0) continue;
printf("%-20s: Calls=%-5d | Avg=%-5dus | Max=%-5dus\n",
monitored_funcs[i].name,
s->call_count,
s->total_time_us / s->call_count,
s->max_time_us);
}
printf("-----------------------------------------\n");
}
/* 包装函数模板(通过宏生成) */
#define GENERATE_WRAPPER(orig_func) \
static void orig_func##_wrapper(void *ctx, void *dsc, void *coords_or_points) { \
uint32_t start = lv_tick_get(); \
((typeof(orig_func)*)orig_func)(ctx, dsc, coords_or_points); \
uint32_t elapsed = lv_tick_elaps(start); \
update_stats((draw_func_t)orig_func, elapsed); \
}
// 为每个绘图函数生成包装器
GENERATE_WRAPPER(lv_draw_sw_arc)
GENERATE_WRAPPER(lv_draw_sw_rect)
GENERATE_WRAPPER(lv_draw_sw_bg)
GENERATE_WRAPPER(lv_draw_sw_letter)
GENERATE_WRAPPER(lv_draw_sw_img_decoded)
GENERATE_WRAPPER(lv_draw_sw_line)
GENERATE_WRAPPER(lv_draw_sw_polygon)
GENERATE_WRAPPER(lv_draw_sw_transform)
GENERATE_WRAPPER(lv_draw_sw_wait_for_finish)
GENERATE_WRAPPER(lv_draw_sw_buffer_copy)
GENERATE_WRAPPER(lv_draw_sw_layer_create)
GENERATE_WRAPPER(lv_draw_sw_layer_adjust)
GENERATE_WRAPPER(lv_draw_sw_layer_blend)
GENERATE_WRAPPER(lv_draw_sw_layer_destroy)
源代码中渲染集成
/* 在绘图上下文初始化代码中替换原始函数 */
#include "perf_monitor.h"
void lv_draw_sw_init_ctx(lv_disp_drv_t *drv, lv_draw_ctx_t *draw_ctx) {
lv_draw_sw_ctx_t *draw_sw_ctx = (lv_draw_sw_ctx_t *)draw_ctx;
lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t));
// 使用宏替换所有绘图函数
WRAP_FUNC(lv_draw_sw_arc, lv_draw_sw_arc_wrapper);
WRAP_FUNC(lv_draw_sw_rect, lv_draw_sw_rect_wrapper);
WRAP_FUNC(lv_draw_sw_bg, lv_draw_sw_bg_wrapper);
WRAP_FUNC(lv_draw_sw_letter, lv_draw_sw_letter_wrapper);
WRAP_FUNC(lv_draw_sw_img_decoded, lv_draw_sw_img_decoded_wrapper);
WRAP_FUNC(lv_draw_sw_line, lv_draw_sw_line_wrapper);
WRAP_FUNC(lv_draw_sw_polygon, lv_draw_sw_polygon_wrapper);
#if LV_DRAW_COMPLEX
WRAP_FUNC(lv_draw_sw_transform, lv_draw_sw_transform_wrapper);
#endif
WRAP_FUNC(lv_draw_sw_wait_for_finish, lv_draw_sw_wait_for_finish_wrapper);
WRAP_FUNC(lv_draw_sw_buffer_copy, lv_draw_sw_buffer_copy_wrapper);
WRAP_FUNC(lv_draw_sw_layer_create, lv_draw_sw_layer_create_wrapper);
WRAP_FUNC(lv_draw_sw_layer_adjust, lv_draw_sw_layer_adjust_wrapper);
WRAP_FUNC(lv_draw_sw_layer_blend, lv_draw_sw_layer_blend_wrapper);
WRAP_FUNC(lv_draw_sw_layer_destroy, lv_draw_sw_layer_destroy_wrapper);
draw_sw_ctx->base_draw.draw_arc = lv_draw_sw_arc;
// ... 其他赋值保持不变
draw_sw_ctx->blend = lv_draw_sw_blend_basic;
}
main中调用
/* 主循环中定期打印统计结果 */
while(1) {
lv_task_handler();
lv_tick_inc(5); // 假设系统时基为5ms
static uint32_t last_print = 0;
if (lv_tick_elaps(last_print) > 2000) { // 每2秒打印一次
perf_monitor_print_stats();
last_print = lv_tick_get();
}
}
#include “draw_stats.h”
#include <stdio.h>
/*-----------------------------
-
统计数据结构
---------------------------/
static draw_func_stats_t draw_stats[STATS_COUNT] = {
[STATS_DRAW_ARC] = {“draw_arc”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_RECT] = {“draw_rect”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_BG] = {“draw_bg”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_LETTER] = {“draw_letter”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_IMG_DECODED] = {“draw_img_decoded”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_LINE] = {“draw_line”, 0, 0, 0, UINT32_MAX},
[STATS_DRAW_POLYGON] = {“draw_polygon”, 0, 0, 0, UINT32_MAX},
#if LV_DRAW_COMPLEX
[STATS_DRAW_TRANSFORM] = {“draw_transform”, 0, 0, 0, UINT32_MAX},
#endif
[STATS_WAIT_FOR_FINISH] = {“wait_for_finish”, 0, 0, 0, UINT32_MAX},
[STATS_BUFFER_COPY] = {“buffer_copy”, 0, 0, 0, UINT32_MAX},
[STATS_LAYER_INIT] = {“layer_init”, 0, 0, 0, UINT32_MAX},
[STATS_LAYER_ADJUST] = {“layer_adjust”, 0, 0, 0, UINT32_MAX},
[STATS_LAYER_BLEND] = {“layer_blend”, 0, 0, 0, UINT32_MAX},
[STATS_LAYER_DESTROY] = {“layer_destroy”, 0, 0, 0, UINT32_MAX},
[STATS_BLEND] = {“blend”, 0, 0, 0, UINT32_MAX},
};
/*-----------------------------
-
原始函数指针存储
---------------------------/
#define DEF_ORIG_FUNC(func) static typeof(func)* orig_##func = NULL
DEF_ORIG_FUNC(lv_draw_sw_arc);
DEF_ORIG_FUNC(lv_draw_sw_rect);
DEF_ORIG_FUNC(lv_draw_sw_bg);
DEF_ORIG_FUNC(lv_draw_sw_letter);
DEF_ORIG_FUNC(lv_draw_sw_img_decoded);
DEF_ORIG_FUNC(lv_draw_sw_line);
DEF_ORIG_FUNC(lv_draw_sw_polygon);
#if LV_DRAW_COMPLEX
DEF_ORIG_FUNC(lv_draw_sw_transform);
#endif
DEF_ORIG_FUNC(lv_draw_sw_wait_for_finish);
DEF_ORIG_FUNC(lv_draw_sw_buffer_copy);
DEF_ORIG_FUNC(lv_draw_sw_layer_create);
DEF_ORIG_FUNC(lv_draw_sw_layer_adjust);
DEF_ORIG_FUNC(lv_draw_sw_layer_blend);
DEF_ORIG_FUNC(lv_draw_sw_layer_destroy);
DEF_ORIG_FUNC(lv_draw_sw_blend_basic);
/*-----------------------------
-
包装器宏定义
---------------------------/
#define WRAP_FUNC(func, stats_idx, …)
static void wrapped_##func(VA_ARGS) {
uint32_t start = lv_tick_get();
orig_##func(VA_ARGS);
uint32_t elapsed = lv_tick_elaps(start);
draw_func_stats_t* s = &draw_stats[stats_idx];
s->call_count++;
s->total_time_us += elapsed;
if (elapsed > s->max_time_us) s->max_time_us = elapsed;
if (elapsed < s->min_time_us) s->min_time_us = elapsed;
}
/*-----------------------------
-
生成所有包装器
---------------------------/
WRAP_FUNC(lv_draw_sw_arc, STATS_DRAW_ARC,
lv_draw_ctx_t* ctx, const lv_draw_arc_dsc_t* dsc, const lv_area_t* coords)
WRAP_FUNC(lv_draw_sw_rect, STATS_DRAW_RECT,
lv_draw_ctx_t* ctx, const lv_draw_rect_dsc_t* dsc, const lv_area_t* coords)
WRAP_FUNC(lv_draw_sw_bg, STATS_DRAW_BG,
lv_draw_ctx_t* ctx, const lv_draw_rect_dsc_t* dsc, const lv_area_t* coords)
WRAP_FUNC(lv_draw_sw_letter, STATS_DRAW_LETTER,
lv_draw_ctx_t* ctx, const lv_draw_label_dsc_t* dsc, const lv_point_t* pos,
uint32_t letter, lv_draw_label_glyph_t* glyph_out)
WRAP_FUNC(lv_draw_sw_img_decoded, STATS_DRAW_IMG_DECODED,
lv_draw_ctx_t* ctx, const lv_draw_img_dsc_t* dsc, const lv_area_t* coords,
const uint8_t* map, const lv_draw_img_sup_t* sup, lv_color_format_t cf, void* color_out)
WRAP_FUNC(lv_draw_sw_line, STATS_DRAW_LINE,
lv_draw_ctx_t* ctx, const lv_draw_line_dsc_t* dsc)
WRAP_FUNC(lv_draw_sw_polygon, STATS_DRAW_POLYGON,
lv_draw_ctx_t* ctx, const lv_draw_rect_dsc_t* dsc, const lv_point_t* points,
uint16_t point_cnt)
#if LV_DRAW_COMPLEX
WRAP_FUNC(lv_draw_sw_transform, STATS_DRAW_TRANSFORM,
lv_draw_ctx_t* ctx, const lv_area_t* dest_area, const void* src_buf,
lv_coord_t src_w, lv_coord_t src_h, lv_coord_t src_stride,
const lv_draw_img_dsc_t* draw_dsc, lv_img_cf_t cf, lv_color_t* cbuf,
lv_opa_t* abuf)
#endif
WRAP_FUNC(lv_draw_sw_wait_for_finish, STATS_WAIT_FOR_FINISH,
lv_draw_ctx_t* ctx)
WRAP_FUNC(lv_draw_sw_buffer_copy, STATS_BUFFER_COPY,
lv_draw_ctx_t* ctx, void* dest_buf, const lv_area_t* dest_area,
lv_coord_t dest_stride, const void* src_buf, const lv_area_t* src_area,
lv_coord_t src_stride)
WRAP_FUNC(lv_draw_sw_layer_create, STATS_LAYER_INIT,
lv_draw_ctx_t* ctx, lv_draw_layer_ctx_t* layer_ctx, lv_draw_layer_flags_t flags)
WRAP_FUNC(lv_draw_sw_layer_adjust, STATS_LAYER_ADJUST,
lv_draw_ctx_t* ctx, lv_draw_layer_ctx_t* layer_ctx, lv_draw_layer_flags_t flags)
WRAP_FUNC(lv_draw_sw_layer_blend, STATS_LAYER_BLEND,
lv_draw_ctx_t* ctx, lv_draw_layer_ctx_t* layer_ctx, const lv_draw_img_dsc_t* draw_dsc)
WRAP_FUNC(lv_draw_sw_layer_destroy, STATS_LAYER_DESTROY,
lv_draw_ctx_t* ctx, lv_draw_layer_ctx_t* layer_ctx)
WRAP_FUNC(lv_draw_sw_blend_basic, STATS_BLEND,
lv_draw_ctx_t* ctx, const lv_draw_sw_blend_dsc_t* dsc)
/*-----------------------------
-
核心接口实现
---------------------------/
void draw_stats_init(void) {
// 初始化所有统计项的最小时间
for (int i = 0; i < STATS_COUNT; i++) {
draw_stats[i].min_time_us = UINT32_MAX;
}
}
void draw_stats_print(void) {
LV_LOG_USER("\n========== LVGL Software Draw Statistics ==========");
for (int i = 0; i < STATS_COUNT; i++) {
draw_func_stats_t* s = &draw_stats[i];
if (s->call_count == 0) continue;
LV_LOG_USER("%-20s | Calls: %-5d | Avg: %-5dus | Max: %-5dus | Min: %-5dus",
s->func_name,
s->call_count,
s->call_count > 0 ? s->total_time_us / s->call_count : 0,
s->max_time_us,
s->min_time_us);
}
LV_LOG_USER("===================================================");
}
void lv_draw_sw_init_ctx_wrapped(lv_disp_t* disp, lv_draw_sw_ctx_t* draw_sw_ctx) {
lv_memset_00(draw_sw_ctx, sizeof(lv_draw_sw_ctx_t));
/* 替换所有绘图函数指针 */
#define REPLACE_FUNC(orig, wrapped, field) \
orig_##orig = draw_sw_ctx->base_draw.field; \
draw_sw_ctx->base_draw.field = (typeof(draw_sw_ctx->base_draw.field))wrapped_##wrapped;
REPLACE_FUNC(lv_draw_sw_arc, lv_draw_sw_arc, draw_arc);
REPLACE_FUNC(lv_draw_sw_rect, lv_draw_sw_rect, draw_rect);
REPLACE_FUNC(lv_draw_sw_bg, lv_draw_sw_bg, draw_bg);
REPLACE_FUNC(lv_draw_sw_letter, lv_draw_sw_letter, draw_letter);
REPLACE_FUNC(lv_draw_sw_img_decoded, lv_draw_sw_img_decoded, draw_img_decoded);
REPLACE_FUNC(lv_draw_sw_line, lv_draw_sw_line, draw_line);
REPLACE_FUNC(lv_draw_sw_polygon, lv_draw_sw_polygon, draw_polygon);
#if LV_DRAW_COMPLEX
REPLACE_FUNC(lv_draw_sw_transform, lv_draw_sw_transform, draw_transform);
#endif
REPLACE_FUNC(lv_draw_sw_wait_for_finish, lv_draw_sw_wait_for_finish, wait_for_finish);
REPLACE_FUNC(lv_draw_sw_buffer_copy, lv_draw_sw_buffer_copy, buffer_copy);
REPLACE_FUNC(lv_draw_sw_layer_create, lv_draw_sw_layer_create, layer_init);
REPLACE_FUNC(lv_draw_sw_layer_adjust, lv_draw_sw_layer_adjust, layer_adjust);
REPLACE_FUNC(lv_draw_sw_layer_blend, lv_draw_sw_layer_blend, layer_blend);
REPLACE_FUNC(lv_draw_sw_layer_destroy, lv_draw_sw_layer_destroy, layer_destroy);
/* 特别处理blend函数 */
orig_lv_draw_sw_blend_basic = draw_sw_ctx->blend;
draw_sw_ctx->blend = wrapped_lv_draw_sw_blend_basic;
}