Skip to content

Commit 85906eb

Browse files
feature(lvgl_port): Initial support for SIMD rendering in LVGL
- Assembly source files for LVGL blend API integrated into lvgl_port - Initial assembly assembly implementation of: - ARGB8888 simple fill for esp32s3 and esp32 - RGB565 simple fill for esp32 - Functionality and benchmark test app
1 parent 7e2be83 commit 85906eb

35 files changed

+4219
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ dependencies.lock
77
doxygen_output/**
88
dist
99
__pycache__
10+
gdbinit

components/esp_lvgl_port/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,27 @@ if("usb_host_hid" IN_LIST build_components)
7676
list(APPEND ADD_LIBS idf::usb_host_hid)
7777
endif()
7878

79+
# Include SIMD assembly source code for rendering, only for LVGL 9.x and only for esp32 and esp32s3
80+
if(lvgl_ver VERSION_GREATER_EQUAL "9.0.0")
81+
if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3)
82+
message(VERBOSE "Compiling SIMD")
83+
if(CONFIG_IDF_TARGET_ESP32S3)
84+
file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32s3.S) # Select only esp32s3 related files
85+
else()
86+
file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32.S) # Select only esp32 related files
87+
endif()
88+
list(APPEND ADD_SRCS ${ASM_SRCS})
89+
90+
# Include component libraries, so lvgl component would see lvgl_port includes
91+
idf_component_get_property(lvgl_lib ${lvgl_name} COMPONENT_LIB)
92+
target_include_directories(${lvgl_lib} PRIVATE "include")
93+
94+
# Force link .S files
95+
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_argb8888_esp")
96+
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_rgb565_esp")
97+
endif()
98+
endif()
99+
79100
# Here we create the real lvgl_port_lib
80101
add_library(lvgl_port_lib STATIC
81102
${PORT_PATH}/esp_lvgl_port.c
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#include "lvgl.h"
14+
15+
/*********************
16+
* INCLUDES
17+
*********************/
18+
19+
#if !CONFIG_LV_DRAW_SW_ASM_CUSTOM
20+
#warning "esp_lvgl_port_lv_blend.h included, but CONFIG_LV_DRAW_SW_ASM_CUSTOM not set. Assembly rendering not used"
21+
#else
22+
23+
/*********************
24+
* DEFINES
25+
*********************/
26+
27+
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888
28+
#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc) \
29+
_lv_color_blend_to_argb8888_esp(dsc)
30+
#endif
31+
32+
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565
33+
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) \
34+
_lv_color_blend_to_rgb565_esp(dsc)
35+
#endif
36+
37+
38+
/**********************
39+
* TYPEDEFS
40+
**********************/
41+
42+
typedef struct {
43+
uint32_t opa;
44+
void *dst_buf;
45+
uint32_t dst_w;
46+
uint32_t dst_h;
47+
uint32_t dst_stride;
48+
const void *src_buf;
49+
uint32_t src_stride;
50+
const lv_opa_t *mask_buf;
51+
uint32_t mask_stride;
52+
} asm_dsc_t;
53+
54+
/**********************
55+
* GLOBAL PROTOTYPES
56+
**********************/
57+
58+
extern int lv_color_blend_to_argb8888_esp(asm_dsc_t *asm_dsc);
59+
60+
static inline lv_result_t _lv_color_blend_to_argb8888_esp(lv_draw_sw_blend_fill_dsc_t *dsc)
61+
{
62+
asm_dsc_t asm_dsc = {
63+
.dst_buf = dsc->dest_buf,
64+
.dst_w = dsc->dest_w,
65+
.dst_h = dsc->dest_h,
66+
.dst_stride = dsc->dest_stride,
67+
.src_buf = &dsc->color,
68+
};
69+
70+
return lv_color_blend_to_argb8888_esp(&asm_dsc);
71+
}
72+
73+
extern int lv_color_blend_to_rgb565_esp(asm_dsc_t *asm_dsc);
74+
75+
static inline lv_result_t _lv_color_blend_to_rgb565_esp(lv_draw_sw_blend_fill_dsc_t *dsc)
76+
{
77+
asm_dsc_t asm_dsc = {
78+
.dst_buf = dsc->dest_buf,
79+
.dst_w = dsc->dest_w,
80+
.dst_h = dsc->dest_h,
81+
.dst_stride = dsc->dest_stride,
82+
.src_buf = &dsc->color,
83+
};
84+
85+
return lv_color_blend_to_rgb565_esp(&asm_dsc);
86+
}
87+
88+
#endif // CONFIG_LV_DRAW_SW_ASM_CUSTOM
89+
90+
#ifdef __cplusplus
91+
} /*extern "C"*/
92+
#endif
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
// This is LVGL ARGB8888 simple fill for ESP32 processor
8+
9+
.section .text
10+
.align 4
11+
.global lv_color_blend_to_argb8888_esp
12+
.type lv_color_blend_to_argb8888_esp,@function
13+
14+
// The function implements the following C code:
15+
// void lv_color_blend_to_argb8888(_lv_draw_sw_blend_fill_dsc_t * dsc);
16+
17+
// Input params
18+
//
19+
// dsc - a2
20+
21+
// typedef struct {
22+
// uint32_t opa; l32i 0
23+
// void * dst_buf; l32i 4
24+
// uint32_t dst_w; l32i 8
25+
// uint32_t dst_h; l32i 12
26+
// uint32_t dst_stride; l32i 16
27+
// const void * src_buf; l32i 20
28+
// uint32_t src_stride; l32i 24
29+
// const lv_opa_t * mask_buf; l32i 28
30+
// uint32_t mask_stride; l32i 32
31+
// } asm_dsc_t;
32+
33+
lv_color_blend_to_argb8888_esp:
34+
35+
entry a1, 32
36+
37+
l32i.n a3, a2, 4 // a3 - dest_buff
38+
l32i.n a4, a2, 8 // a4 - dest_w in uint32_t
39+
l32i.n a5, a2, 12 // a5 - dest_h in uint32_t
40+
l32i.n a6, a2, 16 // a6 - dest_stride in bytes
41+
l32i.n a7, a2, 20 // a7 - src_buff (color)
42+
l32i.n a8, a7, 0 // a8 - color as value
43+
slli a11, a4, 2 // a11 - dest_w_bytes = sizeof(uint32_t) * dest_w
44+
45+
movi a7, 0xff000000 // oppactiy mask
46+
or a10, a7, a8 // apply oppacity
47+
48+
srli a9, a4, 2 // a9 - loop_len = dest_w / 4
49+
sub a6, a6, a11 // dest_stride = dest_stride - dest_w_bytes
50+
51+
.outer_loop:
52+
53+
// Run main loop which sets 16 bytes in one loop run
54+
loopnez a9, ._main_loop
55+
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3
56+
s32i.n a10, a3, 4 // save 32 bits from a10 to dest_buff a3
57+
s32i.n a10, a3, 8 // save 32 bits from a10 to dest_buff a3
58+
s32i.n a10, a3, 12 // save 32 bits from a10 to dest_buff a3
59+
addi.n a3, a3, 16 // increment dest_buff pointer by 16 bytes
60+
._main_loop:
61+
62+
// Finish the remaining bytes out of the loop
63+
// Check modulo 8 of the dest_w_bytes, if - then set 8 bytes
64+
bbci a11, 3, _mod_8_check // branch if 2-nd bit of dest_w_bytes is clear
65+
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3, offset 0 bytes
66+
s32i.n a10, a3, 4 // save 32 bits from a10 to dest_buff a3, offset 0 bytes
67+
addi.n a3, a3, 8 // increment dest_buff pointer by 8 bytes
68+
_mod_8_check:
69+
70+
// Check modulo 4 of the dest_w_bytes, if - then set 4 bytes
71+
bbci a11, 2, _mod_4_check // branch if 2-nd bit of dest_w_bytes is clear
72+
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3, offset 0 bytes
73+
addi.n a3, a3, 4 // increment dest_buff pointer by 4 bytes
74+
_mod_4_check:
75+
76+
add a3, a3, a6 // dest_buff + dest_stride
77+
addi.n a5, a5, -1 // decrease the outer loop
78+
bnez a5, .outer_loop
79+
80+
movi.n a2, 1 // return LV_RESULT_OK = 1
81+
retw.n // return

0 commit comments

Comments
 (0)