diff --git a/components/esp_lvgl_port/CMakeLists.txt b/components/esp_lvgl_port/CMakeLists.txt index 8dc53693..a1fba590 100644 --- a/components/esp_lvgl_port/CMakeLists.txt +++ b/components/esp_lvgl_port/CMakeLists.txt @@ -77,12 +77,12 @@ if("usb_host_hid" IN_LIST build_components) endif() # Include SIMD assembly source code for rendering, only for (9.1.0 <= LVG_version < 9.2.0) and only for esp32 and esp32s3 -if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS "9.2.0")) - if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3) +if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS_EQUAL "9.2.0")) + if(CONFIG_IDF_TARGET_ESP32 OR CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32P4) message(VERBOSE "Compiling SIMD") if(CONFIG_IDF_TARGET_ESP32S3) file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32s3.S) # Select only esp32s3 related files - else() + elseif(CONFIG_IDF_TARGET_ESP32) file(GLOB_RECURSE ASM_SRCS ${PORT_PATH}/simd/*_esp32.S) # Select only esp32 related files endif() list(APPEND ADD_SRCS ${ASM_SRCS}) @@ -91,9 +91,16 @@ if((lvgl_ver VERSION_GREATER_EQUAL "9.1.0") AND (lvgl_ver VERSION_LESS "9.2.0")) idf_component_get_property(lvgl_lib ${lvgl_name} COMPONENT_LIB) target_include_directories(${lvgl_lib} PRIVATE "include") + if(CONFIG_IDF_TARGET_ESP32P4) + file(GLOB_RECURSE PPA_SRCS ${PORT_PATH}/ppa/*) + list(APPEND ADD_SRCS ${PPA_SRCS}) + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_malloc_core") + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u esp_ppa_fill_for_lvgl") + else() # Force link .S files - set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_argb8888_esp") - set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_rgb565_esp") + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_argb8888_esp") + set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-u lv_color_blend_to_rgb565_esp") + endif() endif() endif() @@ -114,5 +121,9 @@ target_link_libraries(lvgl_port_lib PRIVATE ${ADD_LIBS} ) +if(CONFIG_IDF_TARGET_ESP32P4) + target_link_libraries(lvgl_port_lib PRIVATE idf::esp_driver_ppa idf::esp_mm) +endif() + # Finally, link the lvgl_port_lib its esp-idf interface library target_link_libraries(${COMPONENT_LIB} INTERFACE lvgl_port_lib) diff --git a/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend.h b/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend.h index c00de1c0..40248d05 100644 --- a/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend.h +++ b/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend.h @@ -18,6 +18,8 @@ extern "C" { #warning "esp_lvgl_port_lv_blend.h included, but CONFIG_LV_DRAW_SW_ASM_CUSTOM not set. Assembly rendering not used" #else +#include "lv_version.h" + /********************* * DEFINES *********************/ @@ -53,16 +55,76 @@ typedef struct { * GLOBAL PROTOTYPES **********************/ +#if ((LVGL_VERSION_MAJOR == 9) && (LVGL_VERSION_MINOR == 1)) + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + lv_color_t color; + lv_opa_t opa; +} bsp_blend_fill_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + const void * src_buf; + int32_t src_stride; + lv_color_format_t src_color_format; + lv_opa_t opa; + lv_blend_mode_t blend_mode; +} bsp_blend_image_dsc_t; + +#elif ((LVGL_VERSION_MAJOR == 9) && (LVGL_VERSION_MINOR == 2)) + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + lv_color_t color; + lv_opa_t opa; + lv_area_t relative_area; +} bsp_blend_fill_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + const void * src_buf; + int32_t src_stride; + lv_color_format_t src_color_format; + lv_opa_t opa; + lv_blend_mode_t blend_mode; + lv_area_t relative_area; /**< The blend area relative to the layer's buffer area. */ + lv_area_t src_area; /**< The original src area. */ +} bsp_blend_image_dsc_t; + +#endif + extern int lv_color_blend_to_argb8888_esp(asm_dsc_t *asm_dsc); -static inline lv_result_t _lv_color_blend_to_argb8888_esp(_lv_draw_sw_blend_fill_dsc_t *dsc) +static inline lv_result_t _lv_color_blend_to_argb8888_esp(void *dsc) { + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; 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, + .dst_buf = fill_dsc->dest_buf, + .dst_w = fill_dsc->dest_w, + .dst_h = fill_dsc->dest_h, + .dst_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, }; return lv_color_blend_to_argb8888_esp(&asm_dsc); @@ -70,14 +132,15 @@ static inline lv_result_t _lv_color_blend_to_argb8888_esp(_lv_draw_sw_blend_fill extern int lv_color_blend_to_rgb565_esp(asm_dsc_t *asm_dsc); -static inline lv_result_t _lv_color_blend_to_rgb565_esp(_lv_draw_sw_blend_fill_dsc_t *dsc) +static inline lv_result_t _lv_color_blend_to_rgb565_esp(void *dsc) { + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; 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, + .dst_buf = fill_dsc->dest_buf, + .dst_w = fill_dsc->dest_w, + .dst_h = fill_dsc->dest_h, + .dst_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, }; return lv_color_blend_to_rgb565_esp(&asm_dsc); diff --git a/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend_ppa.h b/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend_ppa.h new file mode 100644 index 00000000..09e2dcda --- /dev/null +++ b/components/esp_lvgl_port/include/esp_lvgl_port_lv_blend_ppa.h @@ -0,0 +1,407 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ + +#if !CONFIG_LV_DRAW_SW_ASM_CUSTOM +#warning "esp_lvgl_port_lv_blend_ppa.h included, but CONFIG_LV_DRAW_SW_ASM_CUSTOM not set. PPA rendering not used" +#else + +#include "lv_version.h" + +typedef struct { + uint32_t opa; + void * dest_buf; + uint32_t dest_w; + uint32_t dest_h; + uint32_t dest_stride; + const void * src_buf; + uint32_t src_stride; + const lv_opa_t * mask_buf; + uint32_t mask_stride; +} asm_dsc_t; + +// ppa for lvgl +extern int esp_ppa_fill_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size); +extern int esp_ppa_fill_opa_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size); +extern int esp_ppa_blend_area_for_lvgl(asm_dsc_t * dsc, uint32_t dest_px_size, uint8_t src_px_size); +extern int esp_dma2d_convert_for_lvgl(asm_dsc_t * dsc, const uint8_t dest_px_size, uint32_t src_px_size); + +/********************* + * DEFINES + *********************/ + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565(dsc) \ + _lv_color_blend_to_rgb565_esp2d(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB565_WITH_OPA(dsc) \ + _lv_color_blend_to_rgb565_with_opa_esp2d(dsc) +#endif + + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB565(dsc) \ + _lv_rgb565_blend_normal_to_rgb565_esp2d(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_rgb565_blend_normal_to_rgb565_with_opa_esp2d(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_rgb888_blend_normal_to_rgb565_esp2d(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_rgb888_blend_normal_to_rgb565_with_opa_esp2d(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_argb8888_blend_normal_to_rgb565_esp2d(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_argb8888_blend_normal_to_rgb565_with_opa_esp2d(dsc) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888 +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_esp2d(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_COLOR_BLEND_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_color_blend_to_rgb888_with_opa_esp2d(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_esp2d(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB565_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_rgb565_blend_normal_to_rgb888_with_opa_esp2d(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_esp2d(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_RGB888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size, src_px_size) \ + _lv_rgb888_blend_normal_to_rgb888_with_opa_esp2d(dsc, dst_px_size, src_px_size) +#endif + +#ifndef LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888 +#define LV_DRAW_SW_COLOR_BLEND_TO_ARGB8888(dsc) \ + _lv_color_blend_to_argb8888_esp2d(dsc) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888 +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_esp2d(dsc, dst_px_size) +#endif + +#ifndef LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA +#define LV_DRAW_SW_ARGB8888_BLEND_NORMAL_TO_RGB888_WITH_OPA(dsc, dst_px_size) \ + _lv_argb8888_blend_normal_to_rgb888_with_opa_esp2d(dsc, dst_px_size) +#endif + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * GLOBAL PROTOTYPES + **********************/ + +#if ((LVGL_VERSION_MAJOR == 9) && (LVGL_VERSION_MINOR == 1)) + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + lv_color_t color; + lv_opa_t opa; +} bsp_blend_fill_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + const void * src_buf; + int32_t src_stride; + lv_color_format_t src_color_format; + lv_opa_t opa; + lv_blend_mode_t blend_mode; +} bsp_blend_image_dsc_t; + +#elif ((LVGL_VERSION_MAJOR == 9) && (LVGL_VERSION_MINOR == 2)) + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + lv_color_t color; + lv_opa_t opa; + lv_area_t relative_area; +} bsp_blend_fill_dsc_t; + +typedef struct { + void * dest_buf; + int32_t dest_w; + int32_t dest_h; + int32_t dest_stride; + const lv_opa_t * mask_buf; + int32_t mask_stride; + const void * src_buf; + int32_t src_stride; + lv_color_format_t src_color_format; + lv_opa_t opa; + lv_blend_mode_t blend_mode; + lv_area_t relative_area; /**< The blend area relative to the layer's buffer area. */ + lv_area_t src_area; /**< The original src area. */ +} bsp_blend_image_dsc_t; + +#endif + +// Simple fill: ppa fill +static inline lv_result_t _lv_color_blend_to_rgb565_esp2d(void *dsc) +{ + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = fill_dsc->dest_buf, + .dest_w = fill_dsc->dest_w, + .dest_h = fill_dsc->dest_h, + .dest_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, + .opa = fill_dsc->opa, + }; + return esp_ppa_fill_for_lvgl(&asm_dsc, 2); +} + +static inline lv_result_t _lv_color_blend_to_rgb888_esp2d(void *dsc, uint32_t dst_px_size) +{ + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = fill_dsc->dest_buf, + .dest_w = fill_dsc->dest_w, + .dest_h = fill_dsc->dest_h, + .dest_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, + .opa = fill_dsc->opa, + }; + return esp_ppa_fill_for_lvgl(&asm_dsc, dst_px_size); +} + +static inline lv_result_t _lv_color_blend_to_argb8888_esp2d(void *dsc) +{ + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = fill_dsc->dest_buf, + .dest_w = fill_dsc->dest_w, + .dest_h = fill_dsc->dest_h, + .dest_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, + .opa = fill_dsc->opa, + }; + return esp_ppa_fill_for_lvgl(&asm_dsc, 4); +} + +// Blend with opa +static inline lv_result_t _lv_color_blend_to_rgb565_with_opa_esp2d(void *dsc) +{ + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = fill_dsc->dest_buf, + .dest_w = fill_dsc->dest_w, + .dest_h = fill_dsc->dest_h, + .dest_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, + .opa = fill_dsc->opa, + }; + return esp_ppa_fill_opa_for_lvgl(&asm_dsc, 2); +} + +static inline lv_result_t _lv_color_blend_to_rgb888_with_opa_esp2d(void *dsc, + uint32_t dst_px_size) +{ + bsp_blend_fill_dsc_t * fill_dsc = (bsp_blend_fill_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = fill_dsc->dest_buf, + .dest_w = fill_dsc->dest_w, + .dest_h = fill_dsc->dest_h, + .dest_stride = fill_dsc->dest_stride, + .src_buf = &fill_dsc->color, + .opa = fill_dsc->opa, + }; + return esp_ppa_fill_opa_for_lvgl(&asm_dsc, dst_px_size); +} + +// Color convert (including dam2d memcpy) +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_esp2d(void * dsc) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_dma2d_convert_for_lvgl(&asm_dsc, 2, 2); +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_esp2d(void * dsc, + uint32_t dst_px_size) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_dma2d_convert_for_lvgl(&asm_dsc, dst_px_size, 2); +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_esp2d(void * dsc, + uint32_t src_px_size) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_dma2d_convert_for_lvgl(&asm_dsc, src_px_size, 2); +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_esp2d(void * dsc, + uint32_t dst_px_size, + uint32_t src_px_size) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_dma2d_convert_for_lvgl(&asm_dsc, dst_px_size, src_px_size); +} + +// Blend normal +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_esp2d(void * dsc) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_ppa_blend_area_for_lvgl(&asm_dsc, 2, 4); +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_esp2d(void * dsc, + uint32_t dst_px_size) +{ + bsp_blend_image_dsc_t * blend_dsc = (bsp_blend_image_dsc_t *) dsc; + asm_dsc_t asm_dsc = { + .dest_buf = blend_dsc->dest_buf, + .dest_w = blend_dsc->dest_w, + .dest_h = blend_dsc->dest_h, + .dest_stride = blend_dsc->dest_stride, + .src_buf = blend_dsc->src_buf, + .src_stride = blend_dsc->src_stride, + .opa = blend_dsc->opa, + }; + return esp_ppa_blend_area_for_lvgl(&asm_dsc, dst_px_size, 4); +} + + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb565_with_opa_esp2d(void * dsc) +{ + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb565_with_opa_esp2d(void * dsc, + uint32_t src_px_size) +{ + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb565_with_opa_esp2d(void * dsc) +{ + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb565_blend_normal_to_rgb888_with_opa_esp2d(void * dsc, + uint32_t dst_px_size) +{ + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_rgb888_blend_normal_to_rgb888_with_opa_esp2d(void * dsc, + uint32_t dst_px_size, uint32_t src_px_size) +{ + return LV_RESULT_INVALID; +} + +static inline lv_result_t _lv_argb8888_blend_normal_to_rgb888_with_opa_esp2d(void * dsc, + uint32_t dst_px_size) +{ + return LV_RESULT_INVALID; +} + +#endif // CONFIG_LV_DRAW_SW_ASM_CUSTOM + +#ifdef __cplusplus +} /*extern "C"*/ +#endif diff --git a/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c b/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c index 10fc56dc..0c4598c1 100644 --- a/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c +++ b/components/esp_lvgl_port/src/lvgl9/esp_lvgl_port_disp.c @@ -57,6 +57,9 @@ typedef struct { } flags; } lvgl_port_display_ctx_t; +static lv_color_t *buf1 = NULL; +static lv_color_t *buf2 = NULL; + /******************************************************************************* * Function definitions *******************************************************************************/ @@ -80,6 +83,12 @@ static void lvgl_port_display_invalidate_callback(lv_event_t *e); * Public API functions *******************************************************************************/ +void bsp_get_lvgl_buffer(void **buffer1, void **buffer2) +{ + *buffer1 = buf1; + *buffer2 = buf2; +} + lv_display_t *lvgl_port_add_disp(const lvgl_port_display_cfg_t *disp_cfg) { lvgl_port_lock(0); @@ -123,7 +132,7 @@ lv_display_t *lvgl_port_add_disp_dsi(const lvgl_port_display_cfg_t *disp_cfg, co disp_ctx->disp_type = LVGL_PORT_DISP_TYPE_DSI; #if (CONFIG_IDF_TARGET_ESP32P4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)) - esp_lcd_dpi_panel_event_callbacks_t cbs; + esp_lcd_dpi_panel_event_callbacks_t cbs = {0}; if (dsi_cfg->flags.avoid_tearing) { cbs.on_refresh_done = lvgl_port_flush_dpi_vsync_ready_callback; } else { @@ -230,8 +239,6 @@ static lv_display_t *lvgl_port_add_disp_priv(const lvgl_port_display_cfg_t *disp { esp_err_t ret = ESP_OK; lv_display_t *disp = NULL; - lv_color_t *buf1 = NULL; - lv_color_t *buf2 = NULL; uint32_t buffer_size = 0; SemaphoreHandle_t trans_sem = NULL; assert(disp_cfg != NULL); @@ -286,10 +293,14 @@ static lv_display_t *lvgl_port_add_disp_priv(const lvgl_port_display_cfg_t *disp buff_caps |= MALLOC_CAP_DEFAULT; } - /* Use RGB internal buffers for avoid tearing effect */ +#if CONFIG_IDF_TARGET_ESP32P4 + buff_caps |= MALLOC_CAP_CACHE_ALIGNED; +#endif + + /* Use LCD internal buffers for avoid tearing effect */ if (priv_cfg && priv_cfg->avoid_tearing) { -#if CONFIG_IDF_TARGET_ESP32S3 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) buffer_size = disp_cfg->hres * disp_cfg->vres; +#if CONFIG_IDF_TARGET_ESP32S3 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) ESP_GOTO_ON_ERROR(esp_lcd_rgb_panel_get_frame_buffer(disp_cfg->panel_handle, 2, (void *)&buf1, (void *)&buf2), err, TAG, "Get RGB buffers failed"); #elif CONFIG_IDF_TARGET_ESP32P4 && ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) buffer_size = disp_cfg->hres * disp_cfg->vres; @@ -356,11 +367,11 @@ static lv_display_t *lvgl_port_add_disp_priv(const lvgl_port_display_cfg_t *disp err: if (ret != ESP_OK) { - if (buf1) { - free(buf1); + if (disp_ctx->draw_buffs[0]) { + free(disp_ctx->draw_buffs[0]); } - if (buf2) { - free(buf2); + if (disp_ctx->draw_buffs[1]) { + free(disp_ctx->draw_buffs[1]); } if (disp_ctx->draw_buffs[2]) { free(disp_ctx->draw_buffs[2]); diff --git a/components/esp_lvgl_port/src/lvgl9/ppa/bsp_dma2d.c b/components/esp_lvgl_port/src/lvgl9/ppa/bsp_dma2d.c new file mode 100644 index 00000000..f58633be --- /dev/null +++ b/components/esp_lvgl_port/src/lvgl9/ppa/bsp_dma2d.c @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "dma2d_utils.h" +#include "esp_cache.h" +#include "esp_timer.h" + +static char *TAG = "convert"; + +extern int make_addr_and_size_align(uint8_t **addr, uint32_t *size); + +static bool IRAM_ATTR dma2d_m2m_suc_eof_event_cb(void *user_data) +{ + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + + SemaphoreHandle_t sem = (SemaphoreHandle_t)user_data; + xSemaphoreGiveFromISR(sem, &xHigherPriorityTaskWoken); + return (xHigherPriorityTaskWoken == pdTRUE); +} + +static void dma2d_link_dscr_init(uint32_t *head, uint32_t *next, void *buf_ptr, + uint32_t ha, uint32_t va, uint32_t hb, uint32_t vb, + uint32_t eof, uint32_t en_2d, uint32_t pbyte, uint32_t mod, + uint32_t bias_x, uint32_t bias_y) +{ + dma2d_descriptor_t *dma2d = (dma2d_descriptor_t *)head; + memset(dma2d, 0, sizeof(dma2d_descriptor_t)); + dma2d->owner = DMA2D_DESCRIPTOR_BUFFER_OWNER_DMA; + dma2d->suc_eof = eof; + dma2d->dma2d_en = en_2d; + dma2d->err_eof = 0; + dma2d->hb_length = hb; + dma2d->vb_size = vb; + dma2d->pbyte = pbyte; + dma2d->ha_length = ha; + dma2d->va_size = va; + dma2d->mode = mod; + dma2d->y = bias_y; + dma2d->x = bias_x; + dma2d->buffer = buf_ptr; + dma2d->next = (dma2d_descriptor_t *)next; +} + +esp_err_t dma2d_color_convert(color_space_pixel_format_t src_format, color_space_pixel_format_t dest_format, + uint32_t block_w, uint32_t block_h, + const uint8_t *src_pic_buf, uint32_t src_offx, uint32_t src_offy, uint32_t src_pic_w, uint32_t src_pic_h, + const uint8_t *dest_pic_buf, uint32_t dest_offx, uint32_t dest_offy, uint32_t dest_pic_w, uint32_t dest_pic_h) +{ + assert(src_pic_buf); + assert(dest_pic_buf); + + int64_t start = esp_timer_get_time(); + dma2d_m2m_trans_config_t m2m_trans_config = {0}; + + if (dma2d_m2m_init() != ESP_OK) { + return ESP_FAIL; + } + + dma2d_descriptor_t *tx_dsc; + dma2d_descriptor_t *rx_dsc; + + // Descriptor and buffer address and size should aligned to 64 bytes (the cacheline size alignment restriction) to be used by CPU + dma2d_descriptor_t *tx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, 1, 64, MALLOC_CAP_SPIRAM); + dma2d_descriptor_t *rx_link_buffer = (dma2d_descriptor_t *)heap_caps_aligned_calloc(64, 1, 64, MALLOC_CAP_SPIRAM); + assert(tx_link_buffer); + assert(rx_link_buffer); + tx_dsc = (dma2d_descriptor_t *)((uint32_t)tx_link_buffer); + rx_dsc = (dma2d_descriptor_t *)((uint32_t)rx_link_buffer); + + dma2d_csc_config_t m2m_dma2d_tx_csc = {0}; + uint16_t src_pbyte = src_format.pixel_format == COLOR_PIXEL_RGB888 ? 3 : 2; + uint16_t dest_pbyte = dest_format.pixel_format == COLOR_PIXEL_RGB888 ? 3 : 2; + + if (src_format.pixel_format == COLOR_PIXEL_RGB888 && dest_format.pixel_format == COLOR_PIXEL_RGB565) { + m2m_dma2d_tx_csc.tx_csc_option = DMA2D_CSC_TX_RGB888_TO_RGB565; + } else if (src_format.pixel_format == COLOR_PIXEL_RGB565 && dest_format.pixel_format == COLOR_PIXEL_RGB888) { + m2m_dma2d_tx_csc.tx_csc_option = DMA2D_CSC_TX_RGB565_TO_RGB888; + } + + const uint8_t *prtx = src_pic_buf; + const uint8_t *prrx = dest_pic_buf; + + uint8_t *src_alignd = src_pic_buf + src_offy * src_pbyte * src_pic_w; + uint32_t src_size_alignd = src_pic_w * block_h * src_pbyte; + make_addr_and_size_align(&src_alignd, &src_size_alignd); + + uint8_t *dest_alignd = dest_pic_buf + dest_pic_w * dest_offy * dest_pbyte; + uint32_t dest_size_alignd = dest_pic_w * block_h * dest_pbyte; + make_addr_and_size_align(&dest_alignd, &dest_size_alignd); + + // Writeback TX buffers and Invalidate RX buffers + esp_cache_msync((void *)src_alignd, src_size_alignd, ESP_CACHE_MSYNC_FLAG_DIR_C2M); + esp_cache_msync((void *)dest_alignd, dest_size_alignd, ESP_CACHE_MSYNC_FLAG_INVALIDATE); + + SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(1, 0); + + dma2d_transfer_ability_t transfer_ability_config = { + .data_burst_length = DMA2D_DATA_BURST_LENGTH_128, + .desc_burst_en = true, + .mb_size = DMA2D_MACRO_BLOCK_SIZE_NONE, + }; + + // DMA description preparation + dma2d_link_dscr_init((uint32_t *)tx_dsc, NULL, (void *)prtx, + src_pic_w, src_pic_h, + block_w, block_h, + 1, 1, dma2d_desc_pixel_format_to_pbyte_value(src_format), + DMA2D_DESCRIPTOR_BLOCK_RW_MODE_SINGLE, src_offx, src_offy); + dma2d_link_dscr_init((uint32_t *)rx_dsc, NULL, (void *)prrx, + dest_pic_w, dest_pic_h, + block_w, block_h, + 0, 1, dma2d_desc_pixel_format_to_pbyte_value(dest_format), + DMA2D_DESCRIPTOR_BLOCK_RW_MODE_SINGLE, dest_offx, dest_offy); + // Writeback the DMA descriptors + esp_cache_msync((void *)tx_dsc, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + esp_cache_msync((void *)rx_dsc, 64, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); + + // Construct dma2d_m2m_trans_config_t structure + m2m_trans_config.tx_desc_base_addr = (intptr_t)tx_dsc; + m2m_trans_config.rx_desc_base_addr = (intptr_t)rx_dsc; + m2m_trans_config.trans_eof_cb = dma2d_m2m_suc_eof_event_cb; + m2m_trans_config.user_data = (void *)counting_sem; + m2m_trans_config.transfer_ability_config = &transfer_ability_config; + m2m_trans_config.tx_csc_config = &m2m_dma2d_tx_csc; + + dma2d_m2m(&m2m_trans_config); + xSemaphoreTake(counting_sem, portMAX_DELAY); + + free(tx_link_buffer); + free(rx_link_buffer); + vSemaphoreDelete(counting_sem); + dma2d_m2m_deinit(); + + int duration = esp_timer_get_time() - start; + uint32_t data_size = block_w * block_h * (src_pbyte + dest_pbyte); + float speed = data_size * 0.95367 / duration; + static uint32_t count = 0; + if (count++ % 21 == 0) { + ESP_LOGI(TAG, "dma2d %s: %d ms, (x:%ld, y:%ld)[w:%ld, h:%ld][spx:%d, dpx:%d], %.1f MB/s", src_pbyte == dest_pbyte ? "memcpy" : "convert", + duration / 1000, dest_offx, dest_offy, block_w, block_h, src_pbyte, dest_pbyte, speed); + } + return ESP_OK; +} diff --git a/components/esp_lvgl_port/src/lvgl9/ppa/bsp_ppa.c b/components/esp_lvgl_port/src/lvgl9/ppa/bsp_ppa.c new file mode 100644 index 00000000..8847fc8f --- /dev/null +++ b/components/esp_lvgl_port/src/lvgl9/ppa/bsp_ppa.c @@ -0,0 +1,625 @@ +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: CC0-1.0 + */ + +#include +#include +#include "driver/ppa.h" +#include "esp_heap_caps.h" +#include "esp_timer.h" +#include "esp_log.h" +#include "lvgl.h" +#include "esp_memory_utils.h" +#include "esp_private/esp_cache_private.h" + +static const char *TAG = "ppa_lvgl"; + +#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(num, align) ((num) & (~((align) - 1))) + +// Need define in others file +extern void bsp_get_lvgl_buffer(void **buffer1, void **buffer2); + +typedef struct { + uint32_t opa; + void * dest_buf; + uint32_t dest_w; + uint32_t dest_h; + uint32_t dest_stride; + const void * src_buf; + uint32_t src_stride; + const lv_opa_t * mask_buf; + uint32_t mask_stride; +} asm_dsc_t; + +size_t get_cache_line_size(const void *addr) +{ + esp_err_t ret = ESP_FAIL; + size_t cache_line_size = 0; + uint32_t heap_caps = esp_ptr_external_ram(addr) ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL; + ret = esp_cache_get_alignment(heap_caps, &cache_line_size); + return ret == ESP_OK ? cache_line_size : 0; +} + +int make_addr_and_size_align(uint8_t **addr, uint32_t *size) +{ + uint8_t *buf = *addr; + uint16_t cache_line = get_cache_line_size(buf); + uint8_t *buf_alignd = (uint8_t *) ALIGN_DOWN((uint32_t)buf, cache_line); + uint32_t len = *size; + len += (buf - buf_alignd); + uint32_t size_align = ALIGN_UP(len, cache_line); + + *addr = buf_alignd; + *size = size_align; + return ESP_OK; +} + +#define ENABLE_SPEED_TEST (0) + +#if ENABLE_SPEED_TEST +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#define WIDTH (1920) +#define HEIGHT (1536) +#define SRC_PX_SIZE (3) +#define DEST_PX_SIZE (3) + +int esp_dma2d_convert_for_lvgl(asm_dsc_t * dsc, const uint8_t dest_px_size, uint32_t src_px_size); +int esp_ppa_fill_opa_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size); +int esp_ppa_blend_area_for_lvgl(asm_dsc_t * dsc, uint32_t dest_px_size, uint8_t src_px_size); +int esp_ppa_fill_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size); + +void dma2d_ppa_speed_test(void) +{ + int src_bytes = SRC_PX_SIZE; + int dest_bytes = DEST_PX_SIZE; + int dest_w = WIDTH; + int dest_h = HEIGHT; + int count = 100; + asm_dsc_t dsc = { + .dest_w = dest_w, + .dest_h = dest_h, + .dest_stride = dest_w * dest_bytes, + .opa = 0xFF, + .src_stride = dest_w * src_bytes + }; + dsc.dest_buf = heap_caps_malloc(dsc.dest_stride * dsc.dest_h, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED); + dsc.src_buf = heap_caps_malloc(dsc.src_stride * dsc.dest_h, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED); + for (int i = 0; i < count; i++) { + esp_dma2d_convert_for_lvgl(&dsc, dest_bytes, src_bytes); + } + for (int i = 0; i < count; i++) { + esp_ppa_fill_for_lvgl(&dsc, dest_bytes); + } + for (int i = 0; i < count; i++) { + esp_ppa_blend_area_for_lvgl(&dsc, dest_bytes, src_bytes); + } + for (int i = 0; i < count; i++) { + esp_ppa_fill_opa_for_lvgl(&dsc, dest_bytes); + } + vTaskDelay(0xFFFFFFFF); +} + +static lv_result_t bsp_get_lvgl_info(uint32_t *pic_w, uint32_t *pic_h, uint32_t *stride) +{ + *pic_w = WIDTH; + *pic_h = HEIGHT; + *stride = WIDTH * DEST_PX_SIZE; + return LV_RESULT_OK; +} + +static lv_result_t find_start_addr_and_offset(const uint8_t *src_buf, uint8_t **pic_addr, uint32_t *offsetx, uint32_t *offsety) +{ + *pic_addr = src_buf; + *offsetx = 0; + *offsety = 0; + return LV_RESULT_OK; +} + +static lv_result_t _check_arg(uint32_t dest_w, uint32_t dest_h, const uint8_t *mask_buf) +{ + return LV_RESULT_OK; +} + +static lv_result_t ppa_blend_get_color_mode_by_px_size(int px_size, uint32_t *mode) +{ + px_size = DEST_PX_SIZE; + ppa_blend_color_mode_t color_mode = PPA_BLEND_COLOR_MODE_RGB565; + if (px_size == 2) { + color_mode = PPA_BLEND_COLOR_MODE_RGB565; + } else if (px_size == 3) { + color_mode = PPA_BLEND_COLOR_MODE_RGB888; + } else if (px_size == 4) { + color_mode = PPA_BLEND_COLOR_MODE_ARGB8888; + } else { + return LV_RESULT_INVALID; + } + *mode = color_mode; + return LV_RESULT_OK; +} + +static lv_result_t ppa_get_default_color_mode(uint32_t *color_mode) +{ + if (DEST_PX_SIZE == 2) { + *color_mode = PPA_FILL_COLOR_MODE_RGB565; + } else if (DEST_PX_SIZE == 3) { + *color_mode = PPA_FILL_COLOR_MODE_RGB888; + } else if (DEST_PX_SIZE == 4) { + *color_mode = PPA_FILL_COLOR_MODE_ARGB8888; + } + return LV_RESULT_OK; +} + +#else // ENABLE_SPEED_TEST + +static lv_result_t bsp_get_lvgl_info(uint32_t *pic_w, uint32_t *pic_h, uint32_t *stride) +{ + lv_display_t *disp = lv_display_get_default(); + if (disp == NULL) { + return LV_RESULT_INVALID; + } + *pic_w = lv_display_get_horizontal_resolution(disp); + *pic_h = lv_display_get_vertical_resolution(disp); + lv_color_format_t cf = lv_display_get_color_format(disp); + *stride = lv_draw_buf_width_to_stride(*pic_w, cf); + return LV_RESULT_OK; +} + +static lv_result_t find_start_addr_and_offset(const uint8_t *src_buf, uint8_t **pic_addr, uint32_t *offsetx, uint32_t *offsety) +{ + uint8_t *buf1, *buf2, *addr; + uint32_t pic_w, pic_h, stride; + if (bsp_get_lvgl_info(&pic_w, &pic_h, &stride) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + uint32_t pic_size = stride * pic_h; + bsp_get_lvgl_buffer((void **)&buf1, (void **)&buf2); + uint32_t cache_line_size = get_cache_line_size(src_buf); + if (src_buf >= buf1 && src_buf < buf1 + pic_size) { + addr = buf1; + } else if (src_buf >= buf2 && src_buf < buf2 + pic_size) { + addr = buf2; + } else if ((uint32_t)src_buf == ALIGN_UP((uint32_t)src_buf, cache_line_size)) { + *pic_addr = src_buf; + *offsetx = 0; + *offsety = 0; + return LV_RESULT_OK; + } else { + return LV_RESULT_INVALID; + } + cache_line_size = get_cache_line_size(addr); + if ((uint32_t)addr != ALIGN_UP((uint32_t)addr, cache_line_size)) { + return LV_RESULT_INVALID; + } + + int pixel_size = stride / pic_w; + uint32_t pixel_num = (src_buf - addr) / pixel_size; + *pic_addr = addr; + *offsetx = pixel_num % pic_w; + *offsety = pixel_num / pic_w; + return LV_RESULT_OK; +} + +static lv_result_t _check_arg(uint32_t dest_w, uint32_t dest_h, const uint8_t *mask_buf) +{ + if (lv_display_get_color_format(NULL) == LV_COLOR_FORMAT_XRGB8888) { + return LV_RESULT_INVALID; + } + + uint32_t width = lv_display_get_horizontal_resolution(NULL); + if (dest_w * dest_h < width * 20 || mask_buf != NULL) { + return LV_RESULT_INVALID; + } + return LV_RESULT_OK; +} + +static lv_result_t ppa_blend_get_color_mode_by_px_size(int px_size, uint32_t *mode) +{ + ppa_blend_color_mode_t color_mode = PPA_BLEND_COLOR_MODE_RGB565; + if (px_size == 2) { + color_mode = PPA_BLEND_COLOR_MODE_RGB565; + } else if (px_size == 3) { + color_mode = PPA_BLEND_COLOR_MODE_RGB888; + } else if (px_size == 4) { + color_mode = PPA_BLEND_COLOR_MODE_ARGB8888; + } else { + return LV_RESULT_INVALID; + } + *mode = color_mode; + return LV_RESULT_OK; +} + +static lv_result_t ppa_get_default_color_mode(uint32_t *color_mode) +{ + lv_color_format_t cf = lv_display_get_color_format(NULL); + if (cf == LV_COLOR_FORMAT_RGB565) { + *color_mode = PPA_FILL_COLOR_MODE_RGB565; + } else if (cf == LV_COLOR_FORMAT_RGB888) { + *color_mode = PPA_FILL_COLOR_MODE_RGB888; + } else if (cf == LV_COLOR_FORMAT_ARGB8888) { + *color_mode = PPA_FILL_COLOR_MODE_ARGB8888; + } else { + return LV_RESULT_INVALID; + } + return LV_RESULT_OK; +} + +#endif // ENABLE_SPEED_TEST + +static inline uint32_t convert_color_to_uint32(lv_color_t color, uint8_t opa) +{ + return (uint32_t)((uint32_t)opa << 24) + ((uint32_t)color.red << 16) + ((uint32_t)color.green << 8) + (color.blue); +} + +extern esp_err_t dma2d_color_convert(color_space_pixel_format_t src_format, color_space_pixel_format_t dest_format, + uint32_t block_w, uint32_t block_h, + const uint8_t *src_pic_buf, uint32_t src_offx, uint32_t src_offy, uint32_t src_pic_w, uint32_t src_pic_h, + const uint8_t *dest_pic_buf, uint32_t dest_offx, uint32_t dest_offy, uint32_t dest_pic_w, uint32_t dest_pic_h); + +int esp_dma2d_convert_for_lvgl(asm_dsc_t * dsc, const uint8_t dest_px_size, uint32_t src_px_size) +{ + if (_check_arg(dsc->dest_w, dsc->dest_h, dsc->mask_buf) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + if (dest_px_size < 2 || dest_px_size > 3 || src_px_size < 2 || src_px_size > 3) { + return LV_RESULT_INVALID; + } + + uint32_t pic_w, pic_h, stride; + + if (bsp_get_lvgl_info(&pic_w, &pic_h, &stride) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + color_space_pixel_format_t src_format = { + .color_space = COLOR_SPACE_RGB, + .pixel_format = src_px_size == 2 ? COLOR_PIXEL_RGB565 : COLOR_PIXEL_RGB888, + }; + color_space_pixel_format_t dest_format = { + .color_space = COLOR_SPACE_RGB, + .pixel_format = dest_px_size == 2 ? COLOR_PIXEL_RGB565 : COLOR_PIXEL_RGB888, + }; + + uint8_t *dest_pic_buf = NULL; + uint32_t dest_offx = 0; + uint32_t dest_offy = 0; + if (find_start_addr_and_offset(dsc->dest_buf, &dest_pic_buf, &dest_offx, &dest_offy) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + if (dma2d_color_convert(src_format, dest_format, dsc->dest_w, dsc->dest_h, + dsc->src_buf, 0, 0, dsc->src_stride / src_px_size, dsc->dest_h, + dest_pic_buf, dest_offx, dest_offy, pic_w, pic_h) == ESP_FAIL) { + return LV_RESULT_INVALID; + } + + return LV_RESULT_OK; +} + +int esp_ppa_fill_opa_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size) +{ + if (_check_arg(dsc->dest_w, dsc->dest_h, dsc->mask_buf) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + int64_t start = esp_timer_get_time(); + + uint32_t dest_w = dsc->dest_w; + uint32_t dest_h = dsc->dest_h; + uint32_t pic_w, pic_h, stride; + if (bsp_get_lvgl_info(&pic_w, &pic_h, &stride) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint8_t *bg_pic = NULL; + uint32_t bg_offx = 0; + uint32_t bg_offy = 0; + uint32_t bg_color_mode = PPA_BLEND_COLOR_MODE_RGB888; + if (ppa_get_default_color_mode(&bg_color_mode) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + // In fact we need free, but frequent malloc and free memory takes up a lot of time + // So we just malloc once, and do not free + // The max memory consumption is about 1000KB + static uint8_t *fg_pic = NULL; + static uint32_t fg_max_size = 0; + + uint32_t out_buf_size_align = dest_w * dest_h; // fg color format is A8 + size_t cache_line_size = 0; + esp_cache_get_alignment(MALLOC_CAP_SPIRAM, &cache_line_size); + out_buf_size_align = ALIGN_UP(out_buf_size_align, cache_line_size); + if (fg_max_size < out_buf_size_align) { + fg_max_size = out_buf_size_align; + if (fg_pic != NULL) { + free(fg_pic); + } + fg_pic = heap_caps_aligned_calloc(cache_line_size, fg_max_size, sizeof(uint8_t), MALLOC_CAP_SPIRAM); + } + + ppa_blend_color_mode_t fg_color_mode = PPA_BLEND_COLOR_MODE_A8; + ppa_alpha_update_mode_t fg_updata_mode = PPA_ALPHA_FIX_VALUE; + + lv_color_t lv_color = {0}; + memcpy(&lv_color, dsc->src_buf, sizeof(lv_color_t)); + color_pixel_rgb888_data_t fg_rgb_data = { + .r = lv_color.red, + .g = lv_color.green, + .b = lv_color.blue, + }; + + if (find_start_addr_and_offset(dsc->dest_buf, &bg_pic, &bg_offx, &bg_offy) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + ppa_client_handle_t ppa_client_handle; + ppa_client_config_t ppa_client_config = { + .oper_type = PPA_OPERATION_BLEND, + .max_pending_trans_num = 1, + }; + esp_err_t err = ppa_register_client(&ppa_client_config, &ppa_client_handle); + if (err != ESP_OK) { + printf("ppa register client err: %d\n", err); + goto _err; + } + + uint32_t outbuf_size = ALIGN_UP(stride * pic_h, cache_line_size); + + ppa_blend_oper_config_t oper_config = { + .in_bg.buffer = bg_pic, + .in_bg.pic_w = pic_w, + .in_bg.pic_h = pic_h, + .in_bg.block_w = dest_w, + .in_bg.block_h = dest_h, + .in_bg.block_offset_x = bg_offx, + .in_bg.block_offset_y = bg_offy, + .in_bg.blend_cm = bg_color_mode, + .bg_rgb_swap = 0, + .bg_byte_swap = 0, + .bg_alpha_update_mode = PPA_ALPHA_NO_CHANGE, + + .in_fg.buffer = fg_pic, + .in_fg.pic_w = dest_w, + .in_fg.pic_h = dest_h, + .in_fg.block_w = dest_w, + .in_fg.block_h = dest_h, + .in_fg.block_offset_x = 0, + .in_fg.block_offset_y = 0, + .in_fg.blend_cm = fg_color_mode, + .fg_rgb_swap = 0, + .fg_byte_swap = 0, + .fg_alpha_update_mode = fg_updata_mode, + .fg_alpha_fix_val = dsc->opa, + .fg_fix_rgb_val = fg_rgb_data, + + .out.buffer = bg_pic, + .out.buffer_size = outbuf_size, + .out.pic_w = pic_w, + .out.pic_h = pic_h, + .out.block_offset_x = bg_offx, + .out.block_offset_y = bg_offy, + .out.blend_cm = bg_color_mode, + + .mode = PPA_TRANS_MODE_BLOCKING, + }; + err = ppa_do_blend(ppa_client_handle, &oper_config); + if (err != ESP_OK) { + printf("err: %d\n", err); + goto _err; + } + err = ppa_unregister_client(ppa_client_handle); + if (err != ESP_OK) { + printf("err: %d\n", err); + goto _err; + } + int duration = esp_timer_get_time() - start; + uint32_t data_size = dest_w * dest_h * (dest_px_size + 1); + float speed = data_size * 0.95367 / duration; + static uint32_t count = 0; + if (count++ % 21 == 0) { + ESP_LOGI(TAG, "%s, %d ms, (x:%ld, y:%ld)[w:%ld, h:%ld][spx:%d, dpx:%ld], %.1f MB/s", + __FUNCTION__, duration / 1000, bg_offx, bg_offy, dest_w, dest_h, 1, dest_px_size, speed); + } + + return LV_RESULT_OK; +_err: + return LV_RESULT_INVALID; +} + +int esp_ppa_blend_area_for_lvgl(asm_dsc_t * dsc, uint32_t dest_px_size, uint8_t src_px_size) +{ + if (_check_arg(dsc->dest_w, dsc->dest_h, dsc->mask_buf) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint32_t pic_w, pic_h, stride; + if (bsp_get_lvgl_info(&pic_w, &pic_h, &stride) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + int64_t start = esp_timer_get_time(); + + uint8_t *bg_pic = NULL; + uint32_t bg_offx = 0; + uint32_t bg_offy = 0; + uint32_t bg_color_mode = PPA_BLEND_COLOR_MODE_RGB565; + if (ppa_get_default_color_mode(&bg_color_mode) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint8_t *fg_pic = NULL; + uint32_t fg_offx = 0; + uint32_t fg_offy = 0; + uint32_t fg_color_mode = PPA_BLEND_COLOR_MODE_RGB565; + if (ppa_blend_get_color_mode_by_px_size(src_px_size, &fg_color_mode) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + ppa_alpha_update_mode_t fg_updata_mode = PPA_ALPHA_NO_CHANGE; + + uint32_t dest_w = dsc->dest_w; + uint32_t dest_h = dsc->dest_h; + + if (find_start_addr_and_offset(dsc->dest_buf, &bg_pic, &bg_offx, &bg_offy) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint16_t cache_line_size = CONFIG_CACHE_L2_CACHE_LINE_SIZE; + + if (find_start_addr_and_offset(dsc->src_buf, &fg_pic, &fg_offx, &fg_offy) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + ppa_client_handle_t ppa_client_handle; + ppa_client_config_t ppa_client_config = { + .oper_type = PPA_OPERATION_BLEND, + .max_pending_trans_num = 1, + }; + esp_err_t err = ppa_register_client(&ppa_client_config, &ppa_client_handle); + if (err != ESP_OK) { + printf("ppa register client err: %d\n", err); + goto _err; + } + + uint32_t outbuf_size = ALIGN_UP(stride * pic_h, cache_line_size); + + ppa_blend_oper_config_t oper_config = { + .in_bg.buffer = bg_pic, + .in_bg.pic_w = pic_w, + .in_bg.pic_h = pic_h, + .in_bg.block_w = dest_w, + .in_bg.block_h = dest_h, + .in_bg.block_offset_x = bg_offx, + .in_bg.block_offset_y = bg_offy, + .in_bg.blend_cm = bg_color_mode, + .bg_rgb_swap = 0, + .bg_byte_swap = 0, + .bg_alpha_update_mode = PPA_ALPHA_NO_CHANGE, + + .in_fg.buffer = fg_pic, + .in_fg.pic_w = dest_w, + .in_fg.pic_h = dest_h, + .in_fg.block_w = dest_w, + .in_fg.block_h = dest_h, + .in_fg.block_offset_x = 0, + .in_fg.block_offset_y = 0, + .in_fg.blend_cm = PPA_BLEND_COLOR_MODE_ARGB8888, + .fg_rgb_swap = 0, + .fg_byte_swap = 0, + .fg_alpha_update_mode = fg_updata_mode, + + .out.buffer = bg_pic, + .out.buffer_size = outbuf_size, + .out.pic_w = pic_w, + .out.pic_h = pic_h, + .out.block_offset_x = bg_offx, + .out.block_offset_y = bg_offy, + .out.blend_cm = bg_color_mode, + + .mode = PPA_TRANS_MODE_BLOCKING, + }; + err = ppa_do_blend(ppa_client_handle, &oper_config); + if (err != ESP_OK) { + printf("err: %d\n", err); + goto _err; + } + err = ppa_unregister_client(ppa_client_handle); + if (err != ESP_OK) { + printf("err: %d\n", err); + goto _err; + } + int duration = esp_timer_get_time() - start; + uint32_t data_size = dest_w * dest_h * (dest_px_size * 2 + src_px_size); + float speed = data_size * 0.95367 / duration; + static uint32_t count = 0; + if (count++ % 20 == 0) { + ESP_LOGI(TAG, "%s, %d ms, (x:%ld, y:%ld)[w:%ld, h:%ld][spx:%d, dpx:%ld], %.1f MB/s", + __FUNCTION__, duration / 1000, bg_offx, bg_offy, dest_w, dest_h, src_px_size, dest_px_size, speed); + } + + return LV_RESULT_OK; +_err: + return LV_RESULT_INVALID; +} + +int esp_ppa_fill_for_lvgl(asm_dsc_t *dsc, uint32_t dest_px_size) +{ + if (_check_arg(dsc->dest_w, dsc->dest_h, dsc->mask_buf) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint32_t pic_w, pic_h, stride; + if (bsp_get_lvgl_info(&pic_w, &pic_h, &stride) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + uint8_t *pic_addr = NULL; + uint32_t offsetx = 0; + uint32_t offsety = 0; + uint32_t dest_w = dsc->dest_w; + uint32_t dest_h = dsc->dest_h; + + if (find_start_addr_and_offset(dsc->dest_buf, &pic_addr, &offsetx, &offsety) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + int64_t start = esp_timer_get_time(); + + uint32_t color_mode = PPA_FILL_COLOR_MODE_RGB565; + if (ppa_get_default_color_mode(&color_mode) == LV_RESULT_INVALID) { + return LV_RESULT_INVALID; + } + + lv_color_t lv_color = {0}; + memcpy(&lv_color, dsc->src_buf, sizeof(lv_color_t)); + uint32_t color = convert_color_to_uint32(lv_color, dsc->opa); + + static ppa_client_handle_t ppa_client_handle = NULL; + + uint32_t out_buf_size_align = ALIGN_UP(stride * pic_h, CONFIG_CACHE_L2_CACHE_LINE_SIZE); + if (ppa_client_handle == NULL) { + ppa_client_config_t ppa_client_config = { + .oper_type = PPA_OPERATION_FILL, + .max_pending_trans_num = 1, + }; + esp_err_t err = ppa_register_client(&ppa_client_config, &ppa_client_handle); + if (err != ESP_OK) { + printf("ppa register client err: %d\n", err); + } + } + + ppa_fill_oper_config_t fill_trans_config = { + .fill_block_w = dest_w, + .fill_block_h = dest_h, + .fill_argb_color = { + .val = color, + }, + .mode = PPA_TRANS_MODE_BLOCKING, + + .out = { + .buffer = pic_addr, + .buffer_size = out_buf_size_align, + .pic_w = pic_w, + .pic_h = pic_h, + .block_offset_x = offsetx, + .block_offset_y = offsety, + .fill_cm = color_mode, + } + }; + esp_err_t err = ppa_do_fill(ppa_client_handle, &fill_trans_config); + int duration = esp_timer_get_time() - start; + uint32_t data_size = dsc->dest_w * dsc->dest_h * dest_px_size; + float speed = data_size * 0.95367 / duration; + static uint32_t count = 0; + if (count++ % 21 == 0) { + ESP_LOGI(TAG, "%s, %d ms, (x:%ld, y:%ld)[w:%ld, h:%ld][spx:%d, dpx:%ld], %ld KB, %.1f MB/s", + __FUNCTION__, duration / 1000, offsetx, offsety, dest_w, dest_h, 0, dest_px_size, data_size / 1024, speed); + } + if (err != ESP_OK) { + return LV_RESULT_INVALID; + } + return LV_RESULT_OK; +} diff --git a/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.c b/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.c new file mode 100644 index 00000000..10e81adf --- /dev/null +++ b/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.c @@ -0,0 +1,161 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "dma2d_utils.h" +#include "esp_private/dma2d.h" +#include "soc/dma2d_channel.h" +#include "esp_heap_caps.h" +#include "esp_memory_utils.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_attr.h" +#include "esp_log.h" + +__attribute__((unused)) static const char *TAG = "dma2d_m2m"; + +#if CONFIG_DMA2D_OPERATION_FUNC_IN_IRAM || CONFIG_DMA2D_ISR_IRAM_SAFE +#define DMA2D_M2M_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#else +#define DMA2D_M2M_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT +#endif + +#if CONFIG_DMA2D_ISR_IRAM_SAFE +#define DMA2D_M2M_ATTR IRAM_ATTR +#else +#define DMA2D_M2M_ATTR +#endif + +typedef dma2d_m2m_trans_config_t dma2d_m2m_trans_desc_t; + +typedef struct { + dma2d_m2m_trans_desc_t m2m_trans_desc; + dma2d_trans_config_t dma_chan_desc; + uint32_t dma_trans_placeholder_head; /* Head of the memory for storing the 2D-DMA transaction elm */ +} dma2d_m2m_transaction_t; + +static dma2d_pool_handle_t dma2d_pool_handle; + +esp_err_t dma2d_m2m_init(void) +{ + dma2d_pool_config_t dma2d_pool_config = { + .pool_id = 0 + }; + return dma2d_acquire_pool(&dma2d_pool_config, &dma2d_pool_handle); +} + +esp_err_t dma2d_m2m_deinit(void) +{ + return dma2d_release_pool(dma2d_pool_handle); +} + +static bool DMA2D_M2M_ATTR dma2d_m2m_transaction_done_cb(dma2d_channel_handle_t dma2d_chan, dma2d_event_data_t *event_data, void *user_data) +{ + bool need_yield = false; + dma2d_m2m_transaction_t *trans_config = (dma2d_m2m_transaction_t *)user_data; + dma2d_m2m_trans_desc_t *m2m_trans_desc = &trans_config->m2m_trans_desc; + + if (m2m_trans_desc->trans_eof_cb) { + need_yield |= m2m_trans_desc->trans_eof_cb(m2m_trans_desc->user_data); + } + + free(trans_config); + + return need_yield; +} + +static bool DMA2D_M2M_ATTR dma2d_m2m_transaction_on_picked(uint32_t channel_num, const dma2d_trans_channel_info_t *dma2d_chans, void *user_config) +{ + assert(channel_num == 2 && dma2d_chans && user_config); + dma2d_m2m_transaction_t *trans_config = (dma2d_m2m_transaction_t *)user_config; + dma2d_m2m_trans_desc_t *m2m_trans_desc = &trans_config->m2m_trans_desc; + + // Get the required 2D-DMA channel handles + uint32_t dma_tx_chan_idx = 0; + uint32_t dma_rx_chan_idx = 1; + if (dma2d_chans[0].dir == DMA2D_CHANNEL_DIRECTION_RX) { + dma_tx_chan_idx = 1; + dma_rx_chan_idx = 0; + } + dma2d_channel_handle_t dma_tx_chan = dma2d_chans[dma_tx_chan_idx].chan; + dma2d_channel_handle_t dma_rx_chan = dma2d_chans[dma_rx_chan_idx].chan; + + dma2d_trigger_t trig_periph = { + .periph = DMA2D_TRIG_PERIPH_M2M, + .periph_sel_id = SOC_DMA2D_TRIG_PERIPH_M2M_TX, + }; + dma2d_connect(dma_tx_chan, &trig_periph); + trig_periph.periph_sel_id = SOC_DMA2D_TRIG_PERIPH_M2M_RX; + dma2d_connect(dma_rx_chan, &trig_periph); + + if (m2m_trans_desc->transfer_ability_config) { + dma2d_set_transfer_ability(dma_tx_chan, m2m_trans_desc->transfer_ability_config); + dma2d_set_transfer_ability(dma_rx_chan, m2m_trans_desc->transfer_ability_config); + } + + if (m2m_trans_desc->tx_strategy_config) { + dma2d_apply_strategy(dma_tx_chan, m2m_trans_desc->tx_strategy_config); + } + if (m2m_trans_desc->rx_strategy_config) { + dma2d_apply_strategy(dma_rx_chan, m2m_trans_desc->rx_strategy_config); + } + + if (m2m_trans_desc->tx_csc_config) { + dma2d_configure_color_space_conversion(dma_tx_chan, m2m_trans_desc->tx_csc_config); + } + if (m2m_trans_desc->rx_csc_config) { + dma2d_configure_color_space_conversion(dma_rx_chan, m2m_trans_desc->rx_csc_config); + } + + dma2d_rx_event_callbacks_t dma_cbs = { + .on_recv_eof = dma2d_m2m_transaction_done_cb, + }; + dma2d_register_rx_event_callbacks(dma_rx_chan, &dma_cbs, (void *)trans_config); + + dma2d_set_desc_addr(dma_tx_chan, m2m_trans_desc->tx_desc_base_addr); + dma2d_set_desc_addr(dma_rx_chan, m2m_trans_desc->rx_desc_base_addr); + + dma2d_start(dma_tx_chan); + dma2d_start(dma_rx_chan); + + // No need to yield + return false; +} + +esp_err_t dma2d_m2m(const dma2d_m2m_trans_config_t *trans_config) +{ +#if CONFIG_DMA2D_ISR_IRAM_SAFE + if (trans_config->trans_eof_cb) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(trans_config->trans_eof_cb), + ESP_ERR_INVALID_ARG, TAG, "trans_eof_cb not in IRAM"); + } + if (trans_config->user_data) { + ESP_RETURN_ON_FALSE(esp_ptr_internal(trans_config->user_data), + ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM"); + } +#endif + dma2d_m2m_transaction_t *dma2d_m2m_trans = (dma2d_m2m_transaction_t *)heap_caps_calloc(1, sizeof(dma2d_m2m_transaction_t) + SIZEOF_DMA2D_TRANS_T, DMA2D_M2M_MEM_ALLOC_CAPS); + assert(dma2d_m2m_trans); + + dma2d_m2m_trans->dma_chan_desc.tx_channel_num = 1; + dma2d_m2m_trans->dma_chan_desc.rx_channel_num = 1; + dma2d_m2m_trans->dma_chan_desc.channel_flags = DMA2D_CHANNEL_FUNCTION_FLAG_SIBLING; + dma2d_m2m_trans->dma_chan_desc.channel_flags |= (trans_config->tx_csc_config == NULL) ? 0 : DMA2D_CHANNEL_FUNCTION_FLAG_TX_CSC; + dma2d_m2m_trans->dma_chan_desc.channel_flags |= (trans_config->rx_csc_config == NULL) ? 0 : DMA2D_CHANNEL_FUNCTION_FLAG_RX_CSC; + dma2d_m2m_trans->dma_chan_desc.specified_tx_channel_mask = 0; + dma2d_m2m_trans->dma_chan_desc.specified_rx_channel_mask = 0; + + memcpy(&dma2d_m2m_trans->m2m_trans_desc, trans_config, sizeof(dma2d_m2m_trans_config_t)); + + dma2d_m2m_trans->dma_chan_desc.user_config = (void *)dma2d_m2m_trans; + dma2d_m2m_trans->dma_chan_desc.on_job_picked = dma2d_m2m_transaction_on_picked; + + esp_err_t ret = dma2d_enqueue(dma2d_pool_handle, &dma2d_m2m_trans->dma_chan_desc, (dma2d_trans_t *)&dma2d_m2m_trans->dma_trans_placeholder_head); + if (ret != ESP_OK) { + free(dma2d_m2m_trans); + } + return ret; +} diff --git a/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.h b/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.h new file mode 100644 index 00000000..0447dfb7 --- /dev/null +++ b/components/esp_lvgl_port/src/lvgl9/ppa/dma2d_utils.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_private/dma2d.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the 2D-DMA module to perform memcopy operations + */ +esp_err_t dma2d_m2m_init(void); + +/** + * @brief De-initialize the 2D-DMA module + */ +esp_err_t dma2d_m2m_deinit(void); + +/** + * @brief Callback function when a memcopy operation is done + * + * @param user_data User registered data from `dma2d_m2m_trans_config_t` + * + * @return Whether a task switch is needed after the callback function returns, + * this is usually due to the callback wakes up some high priority task. + */ +typedef bool (*dma2d_m2m_trans_eof_callback_t)(void *user_data); + +/** + * @brief A collection of configuration items for perferming a memcopy operation with 2D-DMA + */ +typedef struct { + intptr_t tx_desc_base_addr; /*!< 2D-DMA TX descriptor address */ + intptr_t rx_desc_base_addr; /*!< 2D-DMA RX descriptor address */ + dma2d_m2m_trans_eof_callback_t trans_eof_cb; /*!< Callback function to be called when the memcopy operation is done */ + void *user_data; /*!< User registered data to be passed into `trans_eof_cb` callback */ + dma2d_transfer_ability_t *transfer_ability_config; /*!< Pointer to a collection of 2D-DMA transfer ability configuration */ + dma2d_strategy_config_t *tx_strategy_config; /*!< Pointer to a collection of 2D-DMA TX strategy configuration */ + dma2d_strategy_config_t *rx_strategy_config; /*!< Pointer to a collection of 2D-DMA RX strategy configuration */ + dma2d_csc_config_t *tx_csc_config; /*!< Pointer to a collection of 2D-DMA TX color space conversion configuration */ + dma2d_csc_config_t *rx_csc_config; /*!< Pointer to a collection of 2D-DMA RX color space conversion configuration */ +} dma2d_m2m_trans_config_t; + +/** + * @brief Do a memcopy operation with 2D-DMA module + * + * @param trans_config Pointer to a collection of configurations for the memcopy operation + * @return + * - ESP_OK: Enqueue the transaction to 2D-DMA pool successfully + * - ESP_ERR_INVALID_ARG: Enqueue the transaction to 2D-DMA pool failed because of invalid argument + */ +esp_err_t dma2d_m2m(const dma2d_m2m_trans_config_t *trans_config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_lvgl_port/src/lvgl9/ppa/esp_malloc.c b/components/esp_lvgl_port/src/lvgl9/ppa/esp_malloc.c new file mode 100644 index 00000000..c8a6cf51 --- /dev/null +++ b/components/esp_lvgl_port/src/lvgl9/ppa/esp_malloc.c @@ -0,0 +1,70 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_heap_caps.h" +#include "lvgl.h" + +#if LV_USE_STDLIB_MALLOC == LV_STDLIB_CUSTOM +void lv_mem_init(void) +{ + return; /*Nothing to init*/ +} + +void lv_mem_deinit(void) +{ + return; /*Nothing to deinit*/ +} + +lv_mem_pool_t lv_mem_add_pool(void * mem, size_t bytes) +{ + /*Not supported*/ + LV_UNUSED(mem); + LV_UNUSED(bytes); + return NULL; +} + +void lv_mem_remove_pool(lv_mem_pool_t pool) +{ + /*Not supported*/ + LV_UNUSED(pool); + return; +} + +void * lv_malloc_core(size_t size) +{ + if (size > 128 * 1024) { + return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED); + } + return malloc(size); +} + +void * lv_realloc_core(void * p, size_t new_size) +{ + if (new_size > 128 * 1024) { + free(p); + return heap_caps_malloc(new_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_CACHE_ALIGNED); + } + return realloc(p, new_size); +} + +void lv_free_core(void * p) +{ + free(p); +} + +void lv_mem_monitor_core(lv_mem_monitor_t * mon_p) +{ + /*Not supported*/ + LV_UNUSED(mon_p); + return; +} + +lv_result_t lv_mem_test_core(void) +{ + /*Not supported*/ + return LV_RESULT_OK; +} +#endif // LV_STDLIB_CUSTOM diff --git a/components/esp_lvgl_port/test_apps/simd/main/lv_blend/include/lv_version.h b/components/esp_lvgl_port/test_apps/simd/main/lv_blend/include/lv_version.h new file mode 100644 index 00000000..d9be15cd --- /dev/null +++ b/components/esp_lvgl_port/test_apps/simd/main/lv_blend/include/lv_version.h @@ -0,0 +1,14 @@ +/** + * @file lv_version.h + * The current version of LVGL + */ + +#ifndef LVGL_VERSION_H +#define LVGL_VERSION_H + +#define LVGL_VERSION_MAJOR 9 +#define LVGL_VERSION_MINOR 1 +#define LVGL_VERSION_PATCH 0 +#define LVGL_VERSION_INFO "" + +#endif /* LVGL_VERSION_H */