feat(draw/sw): add neon 64bit support for rgb565 blending operations (#8590)

This commit is contained in:
André Costa
2025-08-19 20:53:22 +01:00
committed by GitHub
parent 0198e6f591
commit fe5931c587
8 changed files with 2321 additions and 1976 deletions
+8 -1
View File
@@ -52,6 +52,13 @@ To add Arm2D to your project, follow these steps:
Neon Acceleration Neon Acceleration
----------------- -----------------
Several Cortex-A microprocessors support the `Neon SIMD <https://www.arm.com/technologies/neon>`__ instruction set. LVGL has built-in support to improve the performance of software rendering by utilizing Neon instructions. To enable Neon acceleration, set ``LV_USE_DRAW_SW_ASM`` to ``LV_DRAW_SW_ASM_NEON`` in ``lv_conf.h``. Some ARM Cortex-A and Cortex-R processors with the ARMv7 architecture and every ARM Cortex-A and Cortex-R processor from the ARMv8 architecture support the `Neon SIMD <https://www.arm.com/technologies/neon>` instruction set.
LVGL has built-in support to improve the performance of software rendering by utilizing Neon instructions.
Architecture Support
--------------------
Both 32-bit and 64-bit ARM architectures are supported. Simply set ``LV_USE_DRAW_SW_ASM`` to ``LV_DRAW_SW_ASM_NEON`` in ``lv_conf``.
.. note::
All ARM Cortex-A and Cortex-R 64-bit processors include Neon support as a mandatory feature starting with the ARMv8 architecture specification. This makes Neon acceleration universally available on all 64-bit ARM platforms, including current and future ARM architectures.
+4 -4
View File
@@ -63,10 +63,10 @@ fout.write(
#define LV_STDLIB_RTTHREAD 3 #define LV_STDLIB_RTTHREAD 3
#define LV_STDLIB_CUSTOM 255 #define LV_STDLIB_CUSTOM 255
#define LV_DRAW_SW_ASM_NONE 0 #define LV_DRAW_SW_ASM_NONE 0
#define LV_DRAW_SW_ASM_NEON 1 #define LV_DRAW_SW_ASM_NEON 1
#define LV_DRAW_SW_ASM_HELIUM 2 #define LV_DRAW_SW_ASM_HELIUM 2
#define LV_DRAW_SW_ASM_CUSTOM 255 #define LV_DRAW_SW_ASM_CUSTOM 255
#define LV_NEMA_HAL_CUSTOM 0 #define LV_NEMA_HAL_CUSTOM 0
#define LV_NEMA_HAL_STM32 1 #define LV_NEMA_HAL_STM32 1
+20 -4
View File
@@ -155,6 +155,22 @@ static inline void * /* LV_ATTRIBUTE_FAST_MEM */ drawbuf_next_row(const void * b
#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID #define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID
#endif #endif
#ifndef LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565 #ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID #define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(...) LV_RESULT_INVALID
#endif #endif
@@ -933,7 +949,7 @@ static void LV_ATTRIBUTE_FAST_MEM rgb565_swapped_image_blend(lv_draw_sw_blend_im
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) { if(dsc->blend_mode == LV_BLEND_MODE_NORMAL) {
if(mask_buf == NULL && opa >= LV_OPA_MAX) { if(mask_buf == NULL && opa >= LV_OPA_MAX) {
if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc)) { if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565(dsc)) {
uint32_t line_in_bytes = w * 2; uint32_t line_in_bytes = w * 2;
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
lv_memcpy(dest_buf_u16, src_buf_u16, line_in_bytes); lv_memcpy(dest_buf_u16, src_buf_u16, line_in_bytes);
@@ -944,7 +960,7 @@ static void LV_ATTRIBUTE_FAST_MEM rgb565_swapped_image_blend(lv_draw_sw_blend_im
} }
} }
else if(mask_buf == NULL && opa < LV_OPA_MAX) { else if(mask_buf == NULL && opa < LV_OPA_MAX) {
if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc)) { if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc)) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) { for(x = 0; x < w; x++) {
dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], opa); dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], opa);
@@ -955,7 +971,7 @@ static void LV_ATTRIBUTE_FAST_MEM rgb565_swapped_image_blend(lv_draw_sw_blend_im
} }
} }
else if(mask_buf && opa >= LV_OPA_MAX) { else if(mask_buf && opa >= LV_OPA_MAX) {
if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc)) { if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc)) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) { for(x = 0; x < w; x++) {
dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], mask_buf[x]); dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], mask_buf[x]);
@@ -967,7 +983,7 @@ static void LV_ATTRIBUTE_FAST_MEM rgb565_swapped_image_blend(lv_draw_sw_blend_im
} }
} }
else { else {
if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc)) { if(LV_RESULT_INVALID == LV_DRAW_SW_RGB565_SWAPPED_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc)) {
for(y = 0; y < h; y++) { for(y = 0; y < h; y++) {
for(x = 0; x < w; x++) { for(x = 0; x < w; x++) {
dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], LV_OPA_MIX2(mask_buf[x], opa)); dest_buf_u16[x] = lv_color_16_16_mix(lv_color_swap_16(src_buf_u16[x]), dest_buf_u16[x], LV_OPA_MIX2(mask_buf[x], opa));
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,190 @@
/**
* @file lv_draw_sw_blend_neon_to_rgb565.h
*
*/
#ifndef LV_DRAW_SW_BLEND_NEON_TO_RGB565_H
#define LV_DRAW_SW_BLEND_NEON_TO_RGB565_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../../lv_conf_internal.h"
#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON
#include "../../../../misc/lv_types.h"
/*********************
* DEFINES
*********************/
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) lv_draw_sw_blend_neon_color_to_rgb565(dsc)
#endif
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(dsc) lv_draw_sw_blend_neon_color_to_rgb565_with_opa(dsc)
#endif
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_MASK(dsc) lv_draw_sw_blend_neon_color_to_rgb565_with_mask(dsc)
#endif
#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_MIX_MASK_OPA(dsc) lv_draw_sw_blend_neon_color_to_rgb565_with_opa_mask(dsc)
#endif
#ifndef LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565(dsc) lv_draw_sw_blend_neon_l8_to_rgb565(dsc)
#endif
#ifndef LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_L8_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565(dsc) lv_draw_sw_blend_neon_al88_to_rgb565(dsc)
#endif
#ifndef LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) lv_draw_sw_blend_neon_al88_to_rgb565_with_opa(dsc)
#endif
#if 0 /* Disabled as it's not tested */
#ifndef LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) lv_draw_sw_blend_neon_al88_to_rgb565_with_mask(dsc)
#endif
#ifndef LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_AL88_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) lv_draw_sw_blend_neon_al88_to_rgb565_with_opa_mask(dsc)
#endif
#endif
#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc) lv_draw_sw_blend_neon_rgb565_to_rgb565(dsc)
#endif
#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) lv_draw_sw_blend_neon_rgb565_to_rgb565_with_opa(dsc)
#endif
#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) lv_draw_sw_blend_neon_rgb565_to_rgb565_with_mask(dsc)
#endif
#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) lv_draw_sw_blend_neon_rgb565_to_rgb565_with_opa_mask(dsc)
#endif
#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565(dsc, src_px_size) lv_draw_sw_blend_neon_rgb888_to_rgb565(dsc, src_px_size)
#endif
#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc, src_px_size) lv_draw_sw_blend_neon_rgb888_to_rgb565_with_opa(dsc, src_px_size)
#endif
#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc, src_px_size) lv_draw_sw_blend_neon_rgb888_to_rgb565_with_mask(dsc, src_px_size)
#endif
#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc, src_px_size) lv_draw_sw_blend_neon_rgb888_to_rgb565_with_opa_mask(dsc, src_px_size)
#endif
#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565(dsc) lv_draw_sw_blend_neon_argb888_to_rgb565(dsc)
#endif
#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_OPA(dsc) lv_draw_sw_blend_neon_argb888_to_rgb565_with_opa(dsc)
#endif
#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_WITH_MASK(dsc) lv_draw_sw_blend_neon_argb888_to_rgb565_with_mask(dsc)
#endif
#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(dsc) lv_draw_sw_blend_neon_argb888_to_rgb565_with_opa_mask(dsc)
#endif
#ifndef LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565
#define LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565(dsc) lv_draw_sw_blend_neon_argb888_premultiplied_to_rgb565(dsc)
#endif
/*
* Bleding operations with premultiplied argb8888 require division.
* As division is not supported for integer values in neon we don't define these functions
*/
#ifndef LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_WITH_OPA
#define LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_WITH_OPA(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_WITH_MASK
#define LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_WITH_MASK(...) LV_RESULT_INVALID
#endif
#ifndef LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA
#define LV_DRAW_SW_ARGB8888_PREMULTIPLIED_BLEND_NORMAL_TO_RGB565_MIX_MASK_OPA(...) LV_RESULT_INVALID
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
lv_result_t lv_draw_sw_blend_neon_color_to_rgb565(lv_draw_sw_blend_fill_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_color_to_rgb565_with_opa(lv_draw_sw_blend_fill_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_color_to_rgb565_with_mask(lv_draw_sw_blend_fill_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_color_to_rgb565_with_opa_mask(lv_draw_sw_blend_fill_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_l8_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_al88_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_al88_to_rgb565_with_opa(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_al88_to_rgb565_with_mask(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_al88_to_rgb565_with_opa_mask(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_rgb565_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_rgb565_to_rgb565_with_opa(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_rgb565_to_rgb565_with_mask(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_rgb565_to_rgb565_with_opa_mask(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_rgb888_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc, uint8_t src_px_size);
lv_result_t lv_draw_sw_blend_neon_rgb888_to_rgb565_with_opa(lv_draw_sw_blend_image_dsc_t * dsc, uint8_t src_px_size);
lv_result_t lv_draw_sw_blend_neon_rgb888_to_rgb565_with_mask(lv_draw_sw_blend_image_dsc_t * dsc, uint8_t src_px_size);
lv_result_t lv_draw_sw_blend_neon_rgb888_to_rgb565_with_opa_mask(lv_draw_sw_blend_image_dsc_t * dsc,
uint8_t src_px_size);
lv_result_t lv_draw_sw_blend_neon_argb888_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_argb888_premultiplied_to_rgb565(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_argb888_to_rgb565_with_opa(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_argb888_to_rgb565_with_mask(lv_draw_sw_blend_image_dsc_t * dsc);
lv_result_t lv_draw_sw_blend_neon_argb888_to_rgb565_with_opa_mask(lv_draw_sw_blend_image_dsc_t * dsc);
/**********************
* MACROS
**********************/
#endif /* LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_NEON */
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_DRAW_SW_BLEND_NEON_TO_RGB565_H*/
+4 -4
View File
@@ -25,10 +25,10 @@
#define LV_STDLIB_RTTHREAD 3 #define LV_STDLIB_RTTHREAD 3
#define LV_STDLIB_CUSTOM 255 #define LV_STDLIB_CUSTOM 255
#define LV_DRAW_SW_ASM_NONE 0 #define LV_DRAW_SW_ASM_NONE 0
#define LV_DRAW_SW_ASM_NEON 1 #define LV_DRAW_SW_ASM_NEON 1
#define LV_DRAW_SW_ASM_HELIUM 2 #define LV_DRAW_SW_ASM_HELIUM 2
#define LV_DRAW_SW_ASM_CUSTOM 255 #define LV_DRAW_SW_ASM_CUSTOM 255
#define LV_NEMA_HAL_CUSTOM 0 #define LV_NEMA_HAL_CUSTOM 0
#define LV_NEMA_HAL_STM32 1 #define LV_NEMA_HAL_STM32 1