-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
- Loading branch information
1 parent
7f12e73
commit 61b3433
Showing
20 changed files
with
1,697 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,4 @@ dependencies.lock | |
doxygen_output/** | ||
dist | ||
__pycache__ | ||
gdbinit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
components/esp_lvgl_port/include/esp_lvgl_port_lv_blend.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#pragma once | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/********************* | ||
* INCLUDES | ||
*********************/ | ||
#include "esp_log.h" | ||
#include <sdkconfig.h> | ||
#include "lvgl.h" | ||
#include "lv_conf_internal.h" | ||
|
||
#if CONFIG_LV_DRAW_SW_ASM_CUSTOM | ||
|
||
/********************* | ||
* DEFINES | ||
*********************/ | ||
|
||
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888 | ||
#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc) \ | ||
_lv_color_blend_to_argb8888_esp32(dsc) | ||
#endif | ||
|
||
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565 | ||
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) \ | ||
_lv_color_blend_to_rgb565_esp32(dsc) | ||
#endif | ||
|
||
|
||
/********************** | ||
* TYPEDEFS | ||
**********************/ | ||
|
||
typedef struct { | ||
uint32_t opa; | ||
void *dst_buf; | ||
uint32_t dst_w; | ||
uint32_t dst_h; | ||
uint32_t dst_stride; | ||
const void *src_buf; | ||
uint32_t src_stride; | ||
const lv_opa_t *mask_buf; | ||
uint32_t mask_stride; | ||
} asm_dsc_t; | ||
|
||
/********************** | ||
* STATIC VARIABLES | ||
**********************/ | ||
|
||
static const char *TAG_LV_BLEND = "LVGL_PORT_LV_BLEND"; | ||
|
||
/********************** | ||
* GLOBAL PROTOTYPES | ||
**********************/ | ||
|
||
// Extern variable to control switching between Assembly or C implementation, for testing purposes only | ||
extern bool LV_BLEND_USE_ASM; | ||
|
||
extern int lv_color_blend_to_argb8888_esp32_aes3(asm_dsc_t *asm_dsc); // ESP32S3 assembly implementation | ||
extern int lv_color_blend_to_argb8888_esp32_ae32(asm_dsc_t *asm_dsc); // ESP32 assembly implementation | ||
|
||
static inline lv_result_t _lv_color_blend_to_argb8888_esp32(_lv_draw_sw_blend_fill_dsc_t *dsc) | ||
{ | ||
// Check if asm variant should be used (Only for testing) | ||
if (!LV_BLEND_USE_ASM) { | ||
ESP_LOGD(TAG_LV_BLEND, "Calling ANSI impl. of: Simple fill ARGB8888"); | ||
return LV_RESULT_INVALID; | ||
} | ||
|
||
asm_dsc_t asm_dsc = { | ||
.dst_buf = dsc->dest_buf, | ||
.dst_w = dsc->dest_w, | ||
.dst_h = dsc->dest_h, | ||
.dst_stride = dsc->dest_stride, | ||
.src_buf = &dsc->color, | ||
}; | ||
|
||
ESP_LOGD(TAG_LV_BLEND, "Calling ASM impl. of: Simple fill ARGB8888"); | ||
#if CONFIG_IDF_TARGET_ESP32S3 | ||
return lv_color_blend_to_argb8888_esp32_aes3(&asm_dsc); | ||
#elif (CONFIG_IDF_TARGET_ESP32) | ||
return lv_color_blend_to_argb8888_esp32_ae32(&asm_dsc); | ||
#else | ||
return LV_RESULT_INVALID; | ||
#endif | ||
} | ||
|
||
extern int lv_color_blend_to_rgb565_esp32_aes3(asm_dsc_t *asm_dsc); // ESP32S3 assembly implementation | ||
extern int lv_color_blend_to_rgb565_esp32_ae32(asm_dsc_t *asm_dsc); // ESP32 assembly implementation | ||
|
||
static inline lv_result_t _lv_color_blend_to_rgb565_esp32(_lv_draw_sw_blend_fill_dsc_t *dsc) | ||
{ | ||
// Check if asm variant should be used (Only for testing) | ||
if (!LV_BLEND_USE_ASM) { | ||
ESP_LOGD(TAG_LV_BLEND, "Calling ANSI impl. of: Simple fill RGB565"); | ||
return LV_RESULT_INVALID; | ||
} | ||
|
||
asm_dsc_t asm_dsc = { | ||
.dst_buf = dsc->dest_buf, | ||
.dst_w = dsc->dest_w, | ||
.dst_h = dsc->dest_h, | ||
.dst_stride = dsc->dest_stride, | ||
.src_buf = &dsc->color, | ||
}; | ||
|
||
ESP_LOGD(TAG_LV_BLEND, "Calling ASM impl. of: Simple fill RGB565"); | ||
#if CONFIG_IDF_TARGET_ESP32S3 | ||
//return lv_color_blend_to_rgb565_esp32_aes3(&asm_dsc); | ||
return lv_color_blend_to_rgb565_esp32_ae32(&asm_dsc); // TODO ESP32S3 assembly not yet implemented, calling esp32 version for now | ||
// TODO asm version is slower than ANSI | ||
#elif (CONFIG_IDF_TARGET_ESP32) | ||
return lv_color_blend_to_rgb565_esp32_ae32(&asm_dsc); | ||
#else | ||
return LV_RESULT_INVALID; | ||
#endif | ||
} | ||
|
||
#ifdef __cplusplus | ||
} /*extern "C"*/ | ||
#endif | ||
|
||
#endif // CONFIG_LV_DRAW_SW_ASM_CUSTOM |
82 changes: 82 additions & 0 deletions
82
components/esp_lvgl_port/src/lvgl9/simd/lv_color_blend_to_argb8888_ae32.S
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
// This is LVGL ARGB8888 simple fill for ESP32 processor. | ||
.text | ||
.align 4 | ||
.global lv_color_blend_to_argb8888_esp32_ae32 | ||
.global .lv_color_blend_to_argb8888_esp32_ae32_body | ||
.type lv_color_blend_to_argb8888_esp32_ae32,@function | ||
// The function implements the following C code: | ||
// void lv_color_blend_to_argb8888(_lv_draw_sw_blend_fill_dsc_t * dsc); | ||
|
||
// Input params | ||
// | ||
// dsc - a2 | ||
|
||
// typedef struct { | ||
// uint32_t opa; l32i 0 | ||
// void * dst_buf; l32i 4 | ||
// uint32_t dst_w; l32i 8 | ||
// uint32_t dst_h; l32i 12 | ||
// uint32_t dst_stride; l32i 16 | ||
// const void * src_buf; l32i 20 | ||
// uint32_t src_stride; l32i 24 | ||
// const lv_opa_t * mask_buf; l32i 28 | ||
// uint32_t mask_stride; l32i 32 | ||
// } asm_dsc_t; | ||
|
||
lv_color_blend_to_argb8888_esp32_ae32: | ||
|
||
entry a1, 32 | ||
|
||
l32i.n a3, a2, 4 // a3 - dest_buff | ||
l32i.n a4, a2, 8 // a4 - dest_w in uint32_t | ||
l32i.n a5, a2, 12 // a5 - dest_h in uint32_t | ||
l32i.n a6, a2, 16 // a6 - dest_stride in bytes | ||
l32i.n a7, a2, 20 // a7 - src_buff (color) | ||
l32i.n a8, a7, 0 // a8 - color as value | ||
slli a11, a4, 2 // a11 - dest_w_bytes = sizeof(uint32_t) * dest_w | ||
|
||
movi a7, 0xff000000 // oppactiy mask | ||
or a10, a7, a8 // apply oppacity | ||
|
||
.lv_color_blend_to_argb8888_esp32_ae32_body: | ||
|
||
srli a9, a4, 2 // a9 - loop_len = dest_w / 4 | ||
sub a6, a6, a11 // dest_stride = dest_stride - dest_w_bytes | ||
|
||
.outer_loop: | ||
|
||
// Run main loop which sets 16 bytes in one loop run | ||
loopnez a9, ._main_loop | ||
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3 | ||
s32i.n a10, a3, 4 // save 32 bits from a10 to dest_buff a3 | ||
s32i.n a10, a3, 8 // save 32 bits from a10 to dest_buff a3 | ||
s32i.n a10, a3, 12 // save 32 bits from a10 to dest_buff a3 | ||
addi.n a3, a3, 16 // increment dest_buff pointer by 16 bytes | ||
._main_loop: | ||
|
||
// Finish the remaining bytes out of the loop | ||
// Check modulo 8 of the dest_w_bytes, if - then set 8 bytes | ||
bbci a11, 3, _mod_8_check // branch if 2-nd bit of dest_w_bytes is clear | ||
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3, offset 0 bytes | ||
s32i.n a10, a3, 4 // save 32 bits from a10 to dest_buff a3, offset 0 bytes | ||
addi.n a3, a3, 8 // increment dest_buff pointer by 8 bytes | ||
_mod_8_check: | ||
|
||
// Check modulo 4 of the dest_w_bytes, if - then set 4 bytes | ||
bbci a11, 2, _mod_4_check // branch if 2-nd bit of dest_w_bytes is clear | ||
s32i.n a10, a3, 0 // save 32 bits from a10 to dest_buff a3, offset 0 bytes | ||
addi.n a3, a3, 4 // increment dest_buff pointer by 4 bytes | ||
_mod_4_check: | ||
|
||
add a3, a3, a6 // dest_buff + dest_stride | ||
addi.n a5, a5, -1 // decrease the outer loop | ||
bnez a5, .outer_loop | ||
|
||
movi.n a2, 1 // return LV_RESULT_OK = 1 | ||
retw.n // return |
Oops, something went wrong.