diff --git a/components/esp_driver_ppa/src/ppa_blend.c b/components/esp_driver_ppa/src/ppa_blend.c index f8ffab01ee5..51885cd3bee 100644 --- a/components/esp_driver_ppa/src/ppa_blend.c +++ b/components/esp_driver_ppa/src/ppa_blend.c @@ -182,14 +182,35 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); + ESP_RETURN_ON_FALSE(config->in_bg.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->in_bg.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX && + config->in_fg.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->in_fg.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX && + config->out.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->out.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX, + ESP_ERR_INVALID_ARG, TAG, "dimension exceeds DMA2D descriptor field limit"); + ESP_RETURN_ON_FALSE(config->in_bg.block_w > 0 && config->in_bg.block_h > 0 && + config->in_bg.block_offset_x < config->in_bg.pic_w && + config->in_bg.block_w <= (config->in_bg.pic_w - config->in_bg.block_offset_x) && + config->in_bg.block_offset_y < config->in_bg.pic_h && + config->in_bg.block_h <= (config->in_bg.pic_h - config->in_bg.block_offset_y), + ESP_ERR_INVALID_ARG, TAG, "in_bg.block_w/h + in_bg.block_offset_x/y does not fit in the in pic"); + ESP_RETURN_ON_FALSE(config->in_fg.block_w > 0 && config->in_fg.block_h > 0 && + config->in_fg.block_offset_x < config->in_fg.pic_w && + config->in_fg.block_w <= (config->in_fg.pic_w - config->in_fg.block_offset_x) && + config->in_fg.block_offset_y < config->in_fg.pic_h && + config->in_fg.block_h <= (config->in_fg.pic_h - config->in_fg.block_offset_y), + ESP_ERR_INVALID_ARG, TAG, "in_fg.block_w/h + in_fg.block_offset_x/y does not fit in the in pic"); color_space_pixel_format_t out_pixel_format = { .color_type_id = config->out.blend_cm, }; uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits - uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8; + uint32_t out_pic_len = (uint32_t)((uint64_t)config->out.pic_w * config->out.pic_h * out_pixel_depth / 8); ESP_RETURN_ON_FALSE(out_pic_len <= config->out.buffer_size, ESP_ERR_INVALID_ARG, TAG, "out.pic_w/h mismatch with out.buffer_size"); ESP_RETURN_ON_FALSE(config->in_bg.block_w == config->in_fg.block_w && config->in_bg.block_h == config->in_fg.block_h, ESP_ERR_INVALID_ARG, TAG, "in_bg.block_w/h must be equal to in_fg.block_w/h"); + ESP_RETURN_ON_FALSE(config->out.block_offset_x < config->out.pic_w && + config->in_fg.block_w <= (config->out.pic_w - config->out.block_offset_x) && + config->out.block_offset_y < config->out.pic_h && + config->in_fg.block_h <= (config->out.pic_h - config->out.block_offset_y), + ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic"); if (config->bg_byte_swap) { PPA_CHECK_CM_SUPPORT_BYTE_SWAP("in_bg.blend", (uint32_t)config->in_bg.blend_cm); } @@ -204,7 +225,6 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf } uint32_t new_bg_alpha_value = 0; if (config->bg_alpha_update_mode == PPA_ALPHA_FIX_VALUE) { - ESP_RETURN_ON_FALSE(config->bg_alpha_fix_val <= 0xFF, ESP_ERR_INVALID_ARG, TAG, "invalid bg_alpha_fix_val"); new_bg_alpha_value = config->bg_alpha_fix_val; } else if (config->bg_alpha_update_mode == PPA_ALPHA_SCALE) { ESP_RETURN_ON_FALSE(config->bg_alpha_scale_ratio > 0 && config->bg_alpha_scale_ratio < 1, ESP_ERR_INVALID_ARG, TAG, "invalid bg_alpha_scale_ratio"); @@ -237,23 +257,23 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf // Usually C2M can let the msync do alignment internally, however, it only do L1-cacheline-size alignment for L1->L2, and then L2-cacheline-size alignment for L2->mem // While M2C direction manual alignment is L2-cacheline-size alignment for mem->L2->L1 // Mismatching writeback and invalidate data size could cause synchronization error if in_bg/fg_buffer and out_buffer are the same one - uint32_t in_bg_ext_window = (uint32_t)config->in_bg.buffer + config->in_bg.block_offset_y * config->in_bg.pic_w * in_bg_pixel_depth / 8; + uint32_t in_bg_ext_window = (uint32_t)config->in_bg.buffer + (uint32_t)((uint64_t)config->in_bg.block_offset_y * config->in_bg.pic_w * in_bg_pixel_depth / 8); uint32_t in_bg_ext_window_aligned = PPA_ALIGN_DOWN(in_bg_ext_window, buf_alignment_size); - uint32_t in_bg_ext_window_len = config->in_bg.pic_w * config->in_bg.block_h * in_bg_pixel_depth / 8; + uint32_t in_bg_ext_window_len = (uint32_t)((uint64_t)config->in_bg.pic_w * config->in_bg.block_h * in_bg_pixel_depth / 8); esp_cache_msync((void *)in_bg_ext_window_aligned, PPA_ALIGN_UP(in_bg_ext_window_len + (in_bg_ext_window - in_bg_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_C2M); color_space_pixel_format_t in_fg_pixel_format = { .color_type_id = config->in_fg.blend_cm, }; uint32_t in_fg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_fg_pixel_format); // bits - uint32_t in_fg_ext_window = (uint32_t)config->in_fg.buffer + config->in_fg.block_offset_y * config->in_fg.pic_w * in_fg_pixel_depth / 8; + uint32_t in_fg_ext_window = (uint32_t)config->in_fg.buffer + (uint32_t)((uint64_t)config->in_fg.block_offset_y * config->in_fg.pic_w * in_fg_pixel_depth / 8); // Same for fg_buffer msync, do manual alignment uint32_t in_fg_ext_window_aligned = PPA_ALIGN_DOWN(in_fg_ext_window, buf_alignment_size); - uint32_t in_fg_ext_window_len = config->in_fg.pic_w * config->in_fg.block_h * in_fg_pixel_depth / 8; + uint32_t in_fg_ext_window_len = (uint32_t)((uint64_t)config->in_fg.pic_w * config->in_fg.block_h * in_fg_pixel_depth / 8); esp_cache_msync((void *)in_fg_ext_window_aligned, PPA_ALIGN_UP(in_fg_ext_window_len + (in_fg_ext_window - in_fg_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_C2M); // Invalidate out_buffer extended window (alignment strict on M2C direction) - uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8; + uint32_t out_ext_window = (uint32_t)config->out.buffer + (uint32_t)((uint64_t)config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8); uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size); - uint32_t out_ext_window_len = config->out.pic_w * config->in_bg.block_h * out_pixel_depth / 8; + uint32_t out_ext_window_len = (uint32_t)((uint64_t)config->out.pic_w * config->in_bg.block_h * out_pixel_depth / 8); esp_cache_msync((void *)out_ext_window_aligned, PPA_ALIGN_UP(out_ext_window_len + (out_ext_window - out_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_M2C); esp_err_t ret = ESP_OK; diff --git a/components/esp_driver_ppa/src/ppa_fill.c b/components/esp_driver_ppa/src/ppa_fill.c index 1983ea3f016..c51b8ee7b33 100644 --- a/components/esp_driver_ppa/src/ppa_fill.c +++ b/components/esp_driver_ppa/src/ppa_fill.c @@ -96,19 +96,27 @@ esp_err_t ppa_do_fill(ppa_client_handle_t ppa_client, const ppa_fill_oper_config uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); + ESP_RETURN_ON_FALSE(config->out.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->out.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX, + ESP_ERR_INVALID_ARG, TAG, "dimension exceeds DMA2D descriptor field limit"); color_space_pixel_format_t out_pixel_format = { .color_type_id = config->out.fill_cm, }; uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); - uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8; + uint32_t out_pic_len = (uint32_t)((uint64_t)config->out.pic_w * config->out.pic_h * out_pixel_depth / 8); ESP_RETURN_ON_FALSE(out_pic_len <= config->out.buffer_size, ESP_ERR_INVALID_ARG, TAG, "out.pic_w/h mismatch with out.buffer_size"); - // To reduce complexity, color_mode, fill_block_w/h correctness are checked in their corresponding LL functions + ESP_RETURN_ON_FALSE(config->fill_block_w > 0 && config->fill_block_h > 0 && + config->out.block_offset_x < config->out.pic_w && + config->fill_block_w <= (config->out.pic_w - config->out.block_offset_x) && + config->out.block_offset_y < config->out.pic_h && + config->fill_block_h <= (config->out.pic_h - config->out.block_offset_y), + ESP_ERR_INVALID_ARG, TAG, "block does not fit in the out pic"); + // To reduce complexity, specific color_mode, fill_block_w/h correctness are checked in their corresponding LL functions // Write back and invalidate necessary data (note that the window content is not continuous in the buffer) // Write back and invalidate buffer extended window (alignment not necessary on C2M direction, but alignment strict on M2C direction) - uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8; + uint32_t out_ext_window = (uint32_t)config->out.buffer + (uint32_t)((uint64_t)config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8); uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size); - uint32_t out_ext_window_len = config->out.pic_w * config->fill_block_h * out_pixel_depth / 8; + uint32_t out_ext_window_len = (uint32_t)((uint64_t)config->out.pic_w * config->fill_block_h * out_pixel_depth / 8); esp_cache_msync((void *)out_ext_window_aligned, PPA_ALIGN_UP(out_ext_window_len + (out_ext_window - out_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_INVALIDATE); esp_err_t ret = ESP_OK; diff --git a/components/esp_driver_ppa/src/ppa_priv.h b/components/esp_driver_ppa/src/ppa_priv.h index a4d3493a153..af36bdd1536 100644 --- a/components/esp_driver_ppa/src/ppa_priv.h +++ b/components/esp_driver_ppa/src/ppa_priv.h @@ -14,6 +14,7 @@ #include "freertos/semphr.h" #include "esp_private/dma2d.h" #include "hal/dma2d_types.h" +#include "hal/dma2d_ll.h" #include "hal/ppa_types.h" #include "hal/ppa_hal.h" #include "esp_pm.h" diff --git a/components/esp_driver_ppa/src/ppa_srm.c b/components/esp_driver_ppa/src/ppa_srm.c index 311bc25d9fe..8032c60059a 100644 --- a/components/esp_driver_ppa/src/ppa_srm.c +++ b/components/esp_driver_ppa/src/ppa_srm.c @@ -192,6 +192,9 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s uint32_t buf_alignment_size = (uint32_t)ppa_client->engine->platform->buf_alignment_size; ESP_RETURN_ON_FALSE(((uint32_t)config->out.buffer & (buf_alignment_size - 1)) == 0 && (config->out.buffer_size & (buf_alignment_size - 1)) == 0, ESP_ERR_INVALID_ARG, TAG, "out.buffer addr or out.buffer_size not aligned to cache line size"); + ESP_RETURN_ON_FALSE(config->in.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->in.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX && + config->out.pic_w <= DMA2D_LL_DESC_2D_FIELD_MAX && config->out.pic_h <= DMA2D_LL_DESC_2D_FIELD_MAX, + ESP_ERR_INVALID_ARG, TAG, "dimension exceeds DMA2D descriptor field limit"); // For YUV420 input/output: in desc, ha/hb/va/vb/x/y must be even number if (config->in.srm_cm == PPA_SRM_COLOR_MODE_YUV420) { ESP_RETURN_ON_FALSE(config->in.pic_h % 2 == 0 && config->in.pic_w % 2 == 0 && @@ -209,14 +212,17 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s config->out.block_offset_x % 2 == 0 && config->out.block_offset_y % 2 == 0, ESP_ERR_INVALID_ARG, TAG, "YUV420 output does not support odd h/w/offset_x/offset_y"); } - ESP_RETURN_ON_FALSE(config->in.block_w <= (config->in.pic_w - config->in.block_offset_x) && + ESP_RETURN_ON_FALSE(config->in.block_w > 0 && config->in.block_h > 0 && + config->in.block_offset_x < config->in.pic_w && + config->in.block_w <= (config->in.pic_w - config->in.block_offset_x) && + config->in.block_offset_y < config->in.pic_h && config->in.block_h <= (config->in.pic_h - config->in.block_offset_y), ESP_ERR_INVALID_ARG, TAG, "in.block_w/h + in.block_offset_x/y does not fit in the in pic"); color_space_pixel_format_t out_pixel_format = { .color_type_id = config->out.srm_cm, }; uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits - uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8; + uint32_t out_pic_len = (uint32_t)((uint64_t)config->out.pic_w * config->out.pic_h * out_pixel_depth / 8); ESP_RETURN_ON_FALSE(out_pic_len <= config->out.buffer_size, ESP_ERR_INVALID_ARG, TAG, "out.pic_w/h mismatch with out.buffer_size"); ESP_RETURN_ON_FALSE(config->scale_x < PPA_LL_SRM_SCALING_INT_MAX && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) && config->scale_y < PPA_LL_SRM_SCALING_INT_MAX && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX), @@ -230,7 +236,10 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s new_block_w = (uint32_t)(config->scale_y * config->in.block_h); new_block_h = (uint32_t)(config->scale_x * config->in.block_w); } - ESP_RETURN_ON_FALSE(new_block_w <= (config->out.pic_w - config->out.block_offset_x) && + ESP_RETURN_ON_FALSE(new_block_w > 0 && new_block_h > 0, ESP_ERR_INVALID_ARG, TAG, "scale makes block size to be 0"); + ESP_RETURN_ON_FALSE(config->out.block_offset_x < config->out.pic_w && + new_block_w <= (config->out.pic_w - config->out.block_offset_x) && + config->out.block_offset_y < config->out.pic_h && new_block_h <= (config->out.pic_h - config->out.block_offset_y), ESP_ERR_INVALID_ARG, TAG, "scale does not fit in the out pic"); if (config->byte_swap) { @@ -255,13 +264,13 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s .color_type_id = config->in.srm_cm, }; uint32_t in_pixel_depth = color_hal_pixel_format_get_bit_depth(in_pixel_format); // bits - uint32_t in_ext_window = (uint32_t)config->in.buffer + config->in.block_offset_y * config->in.pic_w * in_pixel_depth / 8; - uint32_t in_ext_window_len = config->in.pic_w * config->in.block_h * in_pixel_depth / 8; + uint32_t in_ext_window = (uint32_t)config->in.buffer + (uint32_t)((uint64_t)config->in.block_offset_y * config->in.pic_w * in_pixel_depth / 8); + uint32_t in_ext_window_len = (uint32_t)((uint64_t)config->in.pic_w * config->in.block_h * in_pixel_depth / 8); esp_cache_msync((void *)in_ext_window, in_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED); // Invalidate out_buffer extended window (alignment strict on M2C direction) - uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8; + uint32_t out_ext_window = (uint32_t)config->out.buffer + (uint32_t)((uint64_t)config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8); uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size); - uint32_t out_ext_window_len = config->out.pic_w * new_block_h * out_pixel_depth / 8; // actual ext_window_len must be less than or equal to this, since actual block_h <= new_block_h (may round down) + uint32_t out_ext_window_len = (uint32_t)((uint64_t)config->out.pic_w * new_block_h * out_pixel_depth / 8); // actual ext_window_len must be less than or equal to this, since actual block_h <= new_block_h (may round down) assert(out_ext_window + out_ext_window_len <= (uint32_t)config->out.buffer + config->out.buffer_size); esp_cache_msync((void *)out_ext_window_aligned, PPA_ALIGN_UP(out_ext_window_len + (out_ext_window - out_ext_window_aligned), buf_alignment_size), ESP_CACHE_MSYNC_FLAG_DIR_M2C); diff --git a/components/hal/esp32p4/include/hal/dma2d_ll.h b/components/hal/esp32p4/include/hal/dma2d_ll.h index 563ade6167a..a1362724f6c 100644 --- a/components/hal/esp32p4/include/hal/dma2d_ll.h +++ b/components/hal/esp32p4/include/hal/dma2d_ll.h @@ -71,6 +71,7 @@ extern "C" { #define DMA2D_LL_CHANNEL_PERIPH_SEL_BIT_WIDTH (3) #define DMA2D_LL_DESC_ALIGNMENT 8 // Descriptor must be aligned to 8 bytes +#define DMA2D_LL_DESC_2D_FIELD_MAX 0x3FFFU // 2D descriptor width/height/coordinate fields are 14-bit ///////////////////////////////////// Common ///////////////////////////////////////// /**