From dfe50c5952620dd23449b964ef41116cd4255dcc Mon Sep 17 00:00:00 2001 From: Neo Xu Date: Thu, 9 May 2024 05:53:28 +0800 Subject: [PATCH] feat(draw_buf): add LV_DRAW_BUF_INIT macro to meet alignment requirement (#6102) Signed-off-by: Xu Xingliang Co-authored-by: Gabor Kiss-Vamosi --- examples/widgets/canvas/lv_example_canvas_1.c | 7 +++++-- examples/widgets/canvas/lv_example_canvas_2.c | 4 +++- examples/widgets/canvas/lv_example_canvas_3.c | 3 ++- examples/widgets/canvas/lv_example_canvas_4.c | 3 ++- examples/widgets/canvas/lv_example_canvas_5.c | 3 ++- examples/widgets/canvas/lv_example_canvas_7.c | 3 ++- examples/widgets/canvas/lv_example_canvas_8.c | 3 ++- examples/widgets/label/lv_example_label_4.c | 13 ++++++------- src/draw/lv_draw_buf.h | 19 ++++++++++++++----- src/draw/sw/lv_draw_sw_img.c | 5 +++-- src/lv_api_map_v9_0.h | 2 ++ src/widgets/canvas/lv_canvas.h | 2 +- tests/src/test_cases/widgets/test_canvas.c | 4 +++- 13 files changed, 47 insertions(+), 24 deletions(-) diff --git a/examples/widgets/canvas/lv_example_canvas_1.c b/examples/widgets/canvas/lv_example_canvas_1.c index 781855f2fc..5d146f9350 100644 --- a/examples/widgets/canvas/lv_example_canvas_1.c +++ b/examples/widgets/canvas/lv_example_canvas_1.c @@ -27,7 +27,8 @@ void lv_example_canvas_1(void) label_dsc.color = lv_palette_main(LV_PALETTE_ORANGE); label_dsc.text = "Some text on text canvas"; /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf_16bpp, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_RGB565); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf_16bpp, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_RGB565); + LV_DRAW_BUF_INIT_STATIC(draw_buf_16bpp); lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_canvas_set_draw_buf(canvas, &draw_buf_16bpp); @@ -47,7 +48,9 @@ void lv_example_canvas_1(void) /*Test the rotation. It requires another buffer where the original image is stored. *So use previous canvas as image and rotate it to the new canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf_32bpp, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf_32bpp, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf_32bpp); + /*Create a canvas and initialize its palette*/ canvas = lv_canvas_create(lv_screen_active()); lv_canvas_set_draw_buf(canvas, &draw_buf_32bpp); diff --git a/examples/widgets/canvas/lv_example_canvas_2.c b/examples/widgets/canvas/lv_example_canvas_2.c index eb8fdb203c..2ee1fb5635 100644 --- a/examples/widgets/canvas/lv_example_canvas_2.c +++ b/examples/widgets/canvas/lv_example_canvas_2.c @@ -12,7 +12,9 @@ void lv_example_canvas_2(void) lv_obj_set_style_bg_color(lv_screen_active(), lv_palette_lighten(LV_PALETTE_RED, 5), 0); /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); + /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); lv_canvas_set_draw_buf(canvas, &draw_buf); diff --git a/examples/widgets/canvas/lv_example_canvas_3.c b/examples/widgets/canvas/lv_example_canvas_3.c index 75dbba8885..d22b131738 100644 --- a/examples/widgets/canvas/lv_example_canvas_3.c +++ b/examples/widgets/canvas/lv_example_canvas_3.c @@ -10,7 +10,8 @@ void lv_example_canvas_3(void) { /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); diff --git a/examples/widgets/canvas/lv_example_canvas_4.c b/examples/widgets/canvas/lv_example_canvas_4.c index 9678abfb1f..91311afc58 100644 --- a/examples/widgets/canvas/lv_example_canvas_4.c +++ b/examples/widgets/canvas/lv_example_canvas_4.c @@ -10,7 +10,8 @@ void lv_example_canvas_4(void) { /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); diff --git a/examples/widgets/canvas/lv_example_canvas_5.c b/examples/widgets/canvas/lv_example_canvas_5.c index 2ebfd1b0de..c01585760e 100644 --- a/examples/widgets/canvas/lv_example_canvas_5.c +++ b/examples/widgets/canvas/lv_example_canvas_5.c @@ -10,7 +10,8 @@ void lv_example_canvas_5(void) { /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); diff --git a/examples/widgets/canvas/lv_example_canvas_7.c b/examples/widgets/canvas/lv_example_canvas_7.c index d4e2b76ad7..05dfc375bb 100644 --- a/examples/widgets/canvas/lv_example_canvas_7.c +++ b/examples/widgets/canvas/lv_example_canvas_7.c @@ -10,7 +10,8 @@ void lv_example_canvas_7(void) { /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); diff --git a/examples/widgets/canvas/lv_example_canvas_8.c b/examples/widgets/canvas/lv_example_canvas_8.c index e9773c2a38..ef8675f782 100644 --- a/examples/widgets/canvas/lv_example_canvas_8.c +++ b/examples/widgets/canvas/lv_example_canvas_8.c @@ -12,7 +12,8 @@ void lv_example_canvas_8(void) { /*Create a buffer for the canvas*/ - LV_DRAW_BUF_DEFINE(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, CANVAS_WIDTH, CANVAS_HEIGHT, LV_COLOR_FORMAT_ARGB8888); + LV_DRAW_BUF_INIT_STATIC(draw_buf); /*Create a canvas and initialize its palette*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); diff --git a/examples/widgets/label/lv_example_label_4.c b/examples/widgets/label/lv_example_label_4.c index f7fc18337a..89d93255ed 100644 --- a/examples/widgets/label/lv_example_label_4.c +++ b/examples/widgets/label/lv_example_label_4.c @@ -5,11 +5,11 @@ #define MASK_WIDTH 150 #define MASK_HEIGHT 60 -static void generate_mask(uint8_t * mask, int32_t w, int32_t h, const char * txt) +static void generate_mask(lv_draw_buf_t * mask, int32_t w, int32_t h, const char * txt) { /*Create a "8 bit alpha" canvas and clear it*/ lv_obj_t * canvas = lv_canvas_create(lv_screen_active()); - lv_canvas_set_buffer(canvas, mask, w, h, LV_COLOR_FORMAT_L8); + lv_canvas_set_draw_buf(canvas, mask); lv_canvas_fill_bg(canvas, lv_color_black(), LV_OPA_TRANSP); lv_layer_t layer; @@ -36,11 +36,10 @@ static void generate_mask(uint8_t * mask, int32_t w, int32_t h, const char * txt void lv_example_label_4(void) { /* Create the mask of a text by drawing it to a canvas*/ - static uint8_t mask[MASK_WIDTH * MASK_HEIGHT]; - generate_mask(mask, MASK_WIDTH, MASK_HEIGHT, "Text with gradient"); + LV_DRAW_BUF_DEFINE_STATIC(mask, MASK_WIDTH, MASK_HEIGHT, LV_COLOR_FORMAT_L8); + LV_DRAW_BUF_INIT_STATIC(mask); - static lv_draw_buf_t draw_buf; - lv_draw_buf_init(&draw_buf, MASK_WIDTH, MASK_HEIGHT, LV_COLOR_FORMAT_A8, LV_STRIDE_AUTO, mask, sizeof(mask)); + generate_mask(&mask, MASK_WIDTH, MASK_HEIGHT, "Text with gradient"); /* Create an object from where the text will be masked out. * Now it's a rectangle with a gradient but it could be an image too*/ @@ -50,7 +49,7 @@ void lv_example_label_4(void) lv_obj_set_style_bg_color(grad, lv_color_hex(0xff0000), 0); lv_obj_set_style_bg_grad_color(grad, lv_color_hex(0x0000ff), 0); lv_obj_set_style_bg_grad_dir(grad, LV_GRAD_DIR_HOR, 0); - lv_obj_set_style_bitmap_mask_src(grad, &draw_buf, 0); + lv_obj_set_style_bitmap_mask_src(grad, &mask, 0); } #endif diff --git a/src/draw/lv_draw_buf.h b/src/draw/lv_draw_buf.h index 571d24cbca..4fd0ee7bb0 100644 --- a/src/draw/lv_draw_buf.h +++ b/src/draw/lv_draw_buf.h @@ -44,16 +44,18 @@ typedef struct { */ #define _LV_DRAW_BUF_STRIDE(w, cf) \ - ((((w) * LV_COLOR_FORMAT_GET_BPP(cf) + 7) / 8 + (LV_DRAW_BUF_STRIDE_ALIGN) - 1) & ~((LV_DRAW_BUF_STRIDE_ALIGN) - 1)) + LV_ROUND_UP(((w) * LV_COLOR_FORMAT_GET_BPP(cf) + 7) / 8, LV_DRAW_BUF_STRIDE_ALIGN) -#define _LV_DRAW_BUF_SIZE(w, h, cf) \ - (_LV_DRAW_BUF_STRIDE(w, cf) * (h)) +/* Allocate a slightly larger buffer, so we can adjust the start address to meet alignment */ +#define _LV_DRAW_BUF_SIZE(w, h, cf) (_LV_DRAW_BUF_STRIDE(w, cf) * (h) + LV_DRAW_BUF_ALIGN) /** * Define a static draw buffer with the given width, height, and color format. * Stride alignment is set to LV_DRAW_BUF_STRIDE_ALIGN. + * + * For platform that needs special buffer alignment, call LV_DRAW_BUF_INIT_STATIC. */ -#define LV_DRAW_BUF_DEFINE(name, _w, _h, _cf) \ +#define LV_DRAW_BUF_DEFINE_STATIC(name, _w, _h, _cf) \ static uint8_t buf_##name[_LV_DRAW_BUF_SIZE(_w, _h, _cf)]; \ static lv_draw_buf_t name = { \ .header = { \ @@ -70,6 +72,13 @@ typedef struct { .unaligned_data = buf_##name, \ } +#define LV_DRAW_BUF_INIT_STATIC(name) \ + do { \ + lv_image_header_t * header = &name.header; \ + lv_draw_buf_init(&name, header->w, header->h, header->cf, header->stride, buf_##name, sizeof(buf_##name)); \ + lv_draw_buf_set_flag(&name, LV_IMAGE_FLAGS_MODIFIABLE); \ + } while(0) + typedef void * (*lv_draw_buf_malloc_cb)(size_t size, lv_color_format_t color_format); typedef void (*lv_draw_buf_free_cb)(void * draw_buf); @@ -266,7 +275,7 @@ lv_draw_buf_t * lv_draw_buf_dup(const lv_draw_buf_t * draw_buf); lv_draw_buf_t * lv_draw_buf_dup_user(const lv_draw_buf_handlers_t * handlers, const lv_draw_buf_t * draw_buf); /** - * Initialize a draw buf with the given buffer and parameters. + * Initialize a draw buf with the given buffer and parameters. Clear draw buffer flag to zero. * @param draw_buf the draw buf to initialize * @param w the buffer width in pixels * @param h the buffer height in pixels diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index e13e343213..08a431da55 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -240,7 +240,8 @@ static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t lv_area_t mask_area; lv_result_t decoder_res = lv_image_decoder_open(&mask_decoder_dsc, draw_dsc->bitmap_mask_src, NULL); if(decoder_res == LV_RESULT_OK && mask_decoder_dsc.decoded) { - if(mask_decoder_dsc.decoded->header.cf == LV_COLOR_FORMAT_A8) { + if(mask_decoder_dsc.decoded->header.cf == LV_COLOR_FORMAT_A8 || + mask_decoder_dsc.decoded->header.cf == LV_COLOR_FORMAT_L8) { const lv_draw_buf_t * mask_img = mask_decoder_dsc.decoded; blend_dsc.mask_buf = mask_img->data; blend_dsc.mask_stride = mask_img->header.stride; @@ -254,7 +255,7 @@ static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; } else { - LV_LOG_WARN("The mask image doesn'thave A8 format. Drawing the image without mask."); + LV_LOG_WARN("The mask image is not A8/L8 format. Drawing the image without mask."); } } else { diff --git a/src/lv_api_map_v9_0.h b/src/lv_api_map_v9_0.h index c1e55c91d2..713c5ce1be 100644 --- a/src/lv_api_map_v9_0.h +++ b/src/lv_api_map_v9_0.h @@ -39,6 +39,8 @@ extern "C" { #define lv_button_bind_checked lv_obj_bind_checked +#define LV_DRAW_BUF_DEFINE LV_DRAW_BUF_DEFINE_STATIC + /********************** * MACROS **********************/ diff --git a/src/widgets/canvas/lv_canvas.h b/src/widgets/canvas/lv_canvas.h index 9451327785..f581294e5d 100644 --- a/src/widgets/canvas/lv_canvas.h +++ b/src/widgets/canvas/lv_canvas.h @@ -68,7 +68,7 @@ void lv_canvas_set_buffer(lv_obj_t * obj, void * buf, int32_t w, int32_t h, lv_c /** * Set a draw buffer for the canvas. A draw buffer either can be allocated by `lv_draw_buf_create()` - * or defined statically by `LV_DRAW_BUF_DEFINE`. When buffer start address and stride has alignment + * or defined statically by `LV_DRAW_BUF_DEFINE_STATIC`. When buffer start address and stride has alignment * requirement, it's recommended to use `lv_draw_buf_create`. * @param obj pointer to a canvas object * @param draw_buf pointer to a draw buffer diff --git a/tests/src/test_cases/widgets/test_canvas.c b/tests/src/test_cases/widgets/test_canvas.c index 499a3b365c..96a01e31fd 100644 --- a/tests/src/test_cases/widgets/test_canvas.c +++ b/tests/src/test_cases/widgets/test_canvas.c @@ -28,7 +28,9 @@ void test_canvas_functions_invalidate(void) lv_refr_now(NULL); TEST_ASSERT(draw_counter == 0); - LV_DRAW_BUF_DEFINE(draw_buf, 100, 100, LV_COLOR_FORMAT_NATIVE); + LV_DRAW_BUF_DEFINE_STATIC(draw_buf, 100, 100, LV_COLOR_FORMAT_NATIVE); + LV_DRAW_BUF_INIT_STATIC(draw_buf); + lv_canvas_set_draw_buf(canvas, &draw_buf); lv_refr_now(NULL); TEST_ASSERT(draw_counter == 1);