Skip to content

Commit 5a0eb90

Browse files
committed
fix(ppa): fix a few minor issues for ppa srm and blend driver
1. The smallest scale size can be 1/16, not 1/15 2. Fix potential heap corruption if scale to a smaller size (OOB) 3. Fix mismatching writeback and invalidate data size if in_bg/fg_buffer and out_buffer are the same one and L2 cacheline size is larger than L1 cacheline size
1 parent d8b02f5 commit 5a0eb90

File tree

3 files changed

+19
-9
lines changed

3 files changed

+19
-9
lines changed

components/esp_driver_ppa/src/ppa_blend.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,16 +234,22 @@ esp_err_t ppa_do_blend(ppa_client_handle_t ppa_client, const ppa_blend_oper_conf
234234
.color_type_id = config->in_bg.blend_cm,
235235
};
236236
uint32_t in_bg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_bg_pixel_format); // bits
237+
// 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
238+
// While M2C direction manual alignment is L2-cacheline-size alignment for mem->L2->L1
239+
// Mismatching writeback and invalidate data size could cause synchronization error if in_bg/fg_buffer and out_buffer are the same one
237240
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;
241+
uint32_t in_bg_ext_window_aligned = PPA_ALIGN_DOWN(in_bg_ext_window, buf_alignment_size);
238242
uint32_t in_bg_ext_window_len = config->in_bg.pic_w * config->in_bg.block_h * in_bg_pixel_depth / 8;
239-
esp_cache_msync((void *)in_bg_ext_window, in_bg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
243+
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);
240244
color_space_pixel_format_t in_fg_pixel_format = {
241245
.color_type_id = config->in_fg.blend_cm,
242246
};
243247
uint32_t in_fg_pixel_depth = color_hal_pixel_format_get_bit_depth(in_fg_pixel_format); // bits
244248
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;
249+
// Same for fg_buffer msync, do manual alignment
250+
uint32_t in_fg_ext_window_aligned = PPA_ALIGN_DOWN(in_fg_ext_window, buf_alignment_size);
245251
uint32_t in_fg_ext_window_len = config->in_fg.pic_w * config->in_fg.block_h * in_fg_pixel_depth / 8;
246-
esp_cache_msync((void *)in_fg_ext_window, in_fg_ext_window_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED);
252+
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);
247253
// Invalidate out_buffer extended window (alignment strict on M2C direction)
248254
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
249255
uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size);

components/esp_driver_ppa/src/ppa_srm.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -194,14 +194,17 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
194194
config->out.block_offset_x % 2 == 0 && config->out.block_offset_y % 2 == 0,
195195
ESP_ERR_INVALID_ARG, TAG, "YUV420 output does not support odd h/w/offset_x/offset_y");
196196
}
197+
ESP_RETURN_ON_FALSE(config->in.block_w <= (config->in.pic_w - config->in.block_offset_x) &&
198+
config->in.block_h <= (config->in.pic_h - config->in.block_offset_y),
199+
ESP_ERR_INVALID_ARG, TAG, "in.block_w/h + in.block_offset_x/y does not fit in the in pic");
197200
color_space_pixel_format_t out_pixel_format = {
198201
.color_type_id = config->out.srm_cm,
199202
};
200203
uint32_t out_pixel_depth = color_hal_pixel_format_get_bit_depth(out_pixel_format); // bits
201204
uint32_t out_pic_len = config->out.pic_w * config->out.pic_h * out_pixel_depth / 8;
202205
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");
203-
ESP_RETURN_ON_FALSE(config->scale_x < (PPA_LL_SRM_SCALING_INT_MAX + 1) && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) &&
204-
config->scale_y < (PPA_LL_SRM_SCALING_INT_MAX + 1) && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX),
206+
ESP_RETURN_ON_FALSE(config->scale_x < PPA_LL_SRM_SCALING_INT_MAX && config->scale_x >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX) &&
207+
config->scale_y < PPA_LL_SRM_SCALING_INT_MAX && config->scale_y >= (1.0 / PPA_LL_SRM_SCALING_FRAG_MAX),
205208
ESP_ERR_INVALID_ARG, TAG, "invalid scale");
206209
uint32_t new_block_w = 0;
207210
uint32_t new_block_h = 0;
@@ -243,7 +246,8 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
243246
// Invalidate out_buffer extended window (alignment strict on M2C direction)
244247
uint32_t out_ext_window = (uint32_t)config->out.buffer + config->out.block_offset_y * config->out.pic_w * out_pixel_depth / 8;
245248
uint32_t out_ext_window_aligned = PPA_ALIGN_DOWN(out_ext_window, buf_alignment_size);
246-
uint32_t out_ext_window_len = config->out.pic_w * config->in.block_h * out_pixel_depth / 8;
249+
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)
250+
assert(out_ext_window + out_ext_window_len <= (uint32_t)config->out.buffer + config->out.buffer_size);
247251
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);
248252

249253
esp_err_t ret = ESP_OK;
@@ -256,9 +260,9 @@ esp_err_t ppa_do_scale_rotate_mirror(ppa_client_handle_t ppa_client, const ppa_s
256260
ppa_srm_oper_t *srm_trans_desc = (ppa_srm_oper_t *)trans_on_picked_desc->srm_desc;
257261
memcpy(srm_trans_desc, config, sizeof(ppa_srm_oper_config_t));
258262
srm_trans_desc->scale_x_int = (uint32_t)srm_trans_desc->scale_x;
259-
srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * (PPA_LL_SRM_SCALING_FRAG_MAX + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX;
263+
srm_trans_desc->scale_x_frag = (uint32_t)(srm_trans_desc->scale_x * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
260264
srm_trans_desc->scale_y_int = (uint32_t)srm_trans_desc->scale_y;
261-
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * (PPA_LL_SRM_SCALING_FRAG_MAX + 1)) & PPA_LL_SRM_SCALING_FRAG_MAX;
265+
srm_trans_desc->scale_y_frag = (uint32_t)(srm_trans_desc->scale_y * PPA_LL_SRM_SCALING_FRAG_MAX) & (PPA_LL_SRM_SCALING_FRAG_MAX - 1);
262266
srm_trans_desc->alpha_value = new_alpha_value;
263267
srm_trans_desc->data_burst_length = ppa_client->data_burst_length;
264268

components/hal/esp32p4/include/hal/ppa_ll.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ extern "C" {
2424
#define PPA_LL_BLEND0_CLUT_MEM_ADDR_OFFSET 0x400
2525
#define PPA_LL_BLEND1_CLUT_MEM_ADDR_OFFSET 0x800
2626

27-
#define PPA_LL_SRM_SCALING_INT_MAX PPA_SR_SCAL_X_INT_V
28-
#define PPA_LL_SRM_SCALING_FRAG_MAX PPA_SR_SCAL_X_FRAG_V
27+
#define PPA_LL_SRM_SCALING_INT_MAX (PPA_SR_SCAL_X_INT_V + 1)
28+
#define PPA_LL_SRM_SCALING_FRAG_MAX (PPA_SR_SCAL_X_FRAG_V + 1)
2929

3030
// TODO: On P4 ECO2, SRM block size needs update
3131
#define PPA_LL_SRM_DEFAULT_BLOCK_SIZE 18 // 18 x 18 block size

0 commit comments

Comments
 (0)