diff --git a/env_support/cmsis-pack/LVGL.lvgl.1.0.3-alpha.pack b/env_support/cmsis-pack/LVGL.lvgl.1.0.3.pack similarity index 93% rename from env_support/cmsis-pack/LVGL.lvgl.1.0.3-alpha.pack rename to env_support/cmsis-pack/LVGL.lvgl.1.0.3.pack index 1acdb2e4f..d0feb6e14 100644 Binary files a/env_support/cmsis-pack/LVGL.lvgl.1.0.3-alpha.pack and b/env_support/cmsis-pack/LVGL.lvgl.1.0.3.pack differ diff --git a/env_support/cmsis-pack/LVGL.lvgl.pdsc b/env_support/cmsis-pack/LVGL.lvgl.pdsc index dad409eb2..20c85f3c1 100644 --- a/env_support/cmsis-pack/LVGL.lvgl.pdsc +++ b/env_support/cmsis-pack/LVGL.lvgl.pdsc @@ -36,9 +36,10 @@ https://github.com/lvgl/lvgl.git - + - LVGL 8.3.0-dev - Monthly update for April + - Add GPU support for SWM341-DMA2D - LVGL 8.3.0-dev @@ -198,6 +199,7 @@ + @@ -214,6 +216,7 @@ + @@ -330,7 +333,7 @@ - + A 2D image processing library from Arm (i.e. Arm-2D) for All Cortex-M processors including Cortex-M0 diff --git a/env_support/cmsis-pack/LVGL.pidx b/env_support/cmsis-pack/LVGL.pidx index f44c61966..ba6df4baa 100644 --- a/env_support/cmsis-pack/LVGL.pidx +++ b/env_support/cmsis-pack/LVGL.pidx @@ -2,8 +2,8 @@ LVGL https://raw.githubusercontent.com/lvgl/lvgl/master/env_support/cmsis-pack/ - 2022-04-13T19:22:00 + 2022-04-27T00:49:00 - + \ No newline at end of file diff --git a/env_support/cmsis-pack/README.md b/env_support/cmsis-pack/README.md index 7d181d427..d0a4fdfa8 100644 --- a/env_support/cmsis-pack/README.md +++ b/env_support/cmsis-pack/README.md @@ -43,9 +43,11 @@ remove the misleading guide above this code segment. - LV_USE_GPU_STM32_DMA2D - LV_USE_GPU_NXP_PXP - LV_USE_GPU_NXP_VG_LITE -5. Update macro LV_ATTRIBUTE_MEM_ALIGN to force a WORD alignment. + - LV_USE_GPU_SWM341_DMA2D +5. Update macro `LV_ATTRIBUTE_MEM_ALIGN` and `LV_ATTRIBUTE_MEM_ALIGN_SIZE` to force a WORD alignment. ```c -#define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4))) +#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 4 +#define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4))) ``` 6. Update Theme related macros: diff --git a/env_support/cmsis-pack/lv_conf_cmsis.h b/env_support/cmsis-pack/lv_conf_cmsis.h index 6f0fab3f6..c87ede0c3 100644 --- a/env_support/cmsis-pack/lv_conf_cmsis.h +++ b/env_support/cmsis-pack/lv_conf_cmsis.h @@ -22,9 +22,9 @@ /*Swap the 2 bytes of RGB565 color. Useful if the display has an 8-bit interface (e.g. SPI)*/ #define LV_COLOR_16_SWAP 0 -/*Enable more complex drawing routines to manage screens transparency. - *Can be used if the UI is above another layer, e.g. an OSD menu or video player. - *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/ +/*Enable features to draw on transparent background. + *It's required if opa, and transform_* style properties are used. + *Can be also used if the UI is above another layer, e.g. an OSD menu or video player.*/ #define LV_COLOR_SCREEN_TRANSP 0 /* Adjust color mix functions rounding. GPUs might calculate color mix (blending) differently. @@ -82,7 +82,7 @@ #define LV_TICK_CUSTOM 1 #if LV_TICK_CUSTOM extern uint32_t SystemCoreClock; - #define LV_TICK_CUSTOM_INCLUDE "perf_counter.h" + #define LV_TICK_CUSTOM_INCLUDE "perf_counter.h" #if __PER_COUNTER_VER__ < 10902ul #define LV_TICK_CUSTOM_SYS_TIME_EXPR ((uint32_t)get_system_ticks() / (SystemCoreClock / 1000ul)) @@ -127,6 +127,24 @@ #define LV_CIRCLE_CACHE_SIZE 4 #endif /*LV_DRAW_COMPLEX*/ +/** + * "Simple layers" are used when a widget has `style_opa < 255` to buffer the widget into a layer + * and blend it as an image with the given opacity. + * Note that `bg_opa`, `text_opa` etc don't require buffering into layer) + * The widget can be buffered in smaller chunks to avoid using large buffers. + * `draw_area` (`lv_area_t` meaning the area to draw and `px_size` (size of a pixel in bytes) + * can be used the set the buffer size adaptively. + * + * - LV_LAYER_SIMPLE_BUF_SIZE: [bytes] the optimal target buffer size. LVGL will try to allocate it + * - LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE: [bytes] used if `LV_LAYER_SIMPLE_BUF_SIZE` couldn't be allocated. + * + * Both buffer sizes are in bytes. + * "Transformed layers" (where transform_angle/zoom properties are used) use larger buffers + * and can't be drawn in chunks. So these settings affects only widgets with opacity. + */ +#define LV_LAYER_SIMPLE_BUF_SIZE (24 * 1024) +#define LV_LAYER_SIMPLE_FALLBACK_BUF_SIZE LV_MAX(lv_area_get_width(&draw_area) * px_size, 2048) + /*Default image cache size. Image caching keeps the images opened. *If only the built-in image formats are used there is no real advantage of caching. (I.e. if no new image decoder is added) *With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images. @@ -164,6 +182,7 @@ * GPU *-----------*/ + /*Use STM32's DMA2D (aka Chrom Art) GPU*/ #if LV_USE_GPU_STM32_DMA2D /*Must be defined to include path of CMSIS header of target processor @@ -186,7 +205,6 @@ #define LV_USE_GPU_NXP_PXP_AUTO_INIT 0 #endif -/*Use NXP's VG-Lite GPU iMX RTxxx platforms*/ /*Use SDL renderer API*/ #define LV_USE_GPU_SDL 0 @@ -303,11 +321,11 @@ #define LV_ATTRIBUTE_FLUSH_READY /*Required alignment size for buffers*/ -#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 1 +#define LV_ATTRIBUTE_MEM_ALIGN_SIZE 4 /*Will be added where memories needs to be aligned (with -Os data might not be aligned to boundary by default). * E.g. __attribute__((aligned(4)))*/ -#define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4))) +#define LV_ATTRIBUTE_MEM_ALIGN __attribute__((aligned(4))) /*Attribute to mark large constant arrays for example font's bitmaps*/ #define LV_ATTRIBUTE_LARGE_CONST diff --git a/src/draw/arm2d/lv_gpu_arm2d.c b/src/draw/arm2d/lv_gpu_arm2d.c index d2bf8a581..7198966e3 100644 --- a/src/draw/arm2d/lv_gpu_arm2d.c +++ b/src/draw/arm2d/lv_gpu_arm2d.c @@ -11,11 +11,15 @@ #if LV_USE_GPU_ARM2D #include "arm_2d.h" +#include "__arm_2d_impl.h" +#include "__arm_2d_direct.h" /********************* * DEFINES *********************/ +#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) + #if LV_COLOR_DEPTH == 16 #define arm_2d_fill_colour arm_2d_rgb16_fill_colour #define arm_2d_fill_colour_with_alpha arm_2d_rgb565_fill_colour_with_alpha @@ -78,6 +82,8 @@ * STATIC PROTOTYPES **********************/ + + #if __ARM_2D_HAS_HW_ACC__ LV_ATTRIBUTE_FAST_MEM static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, @@ -94,82 +100,15 @@ static bool lv_draw_arm2d_tile_copy(const arm_2d_tile_t * target_tile, arm_2d_tile_t * mask_tile); #else -/* arm-2d direct mode APIs */ -extern -void __arm_2d_impl_colour_filling(color_int * __RESTRICT pTarget, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize, - color_int Colour); - -extern -void __arm_2d_impl_colour_filling_with_opacity( - color_int * __RESTRICT pTargetBase, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize, - color_int Colour, - uint_fast8_t chRatio); - -extern -void __arm_2d_impl_colour_filling_mask( - color_int * __RESTRICT pTarget, - int16_t iTargetStride, - uint8_t * __RESTRICT pchAlpha, - int16_t iAlphaStride, - arm_2d_size_t * __RESTRICT ptCopySize, - color_int Colour); - -extern -void __arm_2d_impl_colour_filling_mask_opacity( - color_int * __RESTRICT pTarget, - int16_t iTargetStride, - uint8_t * __RESTRICT pchAlpha, - int16_t iAlphaStride, - arm_2d_size_t * __RESTRICT ptCopySize, - color_int Colour, - uint8_t chOpacity); - -extern -void __arm_2d_impl_copy(color_int * __RESTRICT pSource, - int16_t iSourceStride, - color_int * __RESTRICT pTarget, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize); - -extern -void __arm_2d_impl_alpha_blending(color_int * __RESTRICT pSource, - int16_t iSourceStride, - color_int * __RESTRICT pTarget, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize, - uint_fast8_t chRatio); - -extern -void __arm_2d_impl_gray8_alpha_blending(uint8_t * __RESTRICT pSource, - int16_t iSourceStride, - uint8_t * __RESTRICT pTarget, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize, - uint_fast8_t chRatio); - -extern -void __arm_2d_impl_src_msk_copy(color_int * __RESTRICT pSourceBase, - int16_t iSourceStride, - uint8_t * __RESTRICT ptSourceMaskBase, - int16_t iSourceMaskStride, - arm_2d_size_t * __RESTRICT ptSourceMaskSize, - color_int * __RESTRICT pTargetBase, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize); - -extern -void __arm_2d_impl_src_chn_msk_copy(color_int * __RESTRICT pSourceBase, - int16_t iSourceStride, - uint32_t * __RESTRICT ptSourceMaskBase, - int16_t iSourceMaskStride, - arm_2d_size_t * __RESTRICT ptSourceMaskSize, - color_int * __RESTRICT pTargetBase, - int16_t iTargetStride, - arm_2d_size_t * __RESTRICT ptCopySize); +static void convert_cb(const lv_area_t * dest_area, + const void * src_buf, + lv_coord_t src_w, + lv_coord_t src_h, + lv_coord_t src_stride, + const lv_draw_img_dsc_t * draw_dsc, + lv_img_cf_t cf, + lv_color_t * cbuf, + lv_opa_t * abuf); LV_ATTRIBUTE_FAST_MEM static bool arm_2d_fill_normal(lv_color_t * dest_buf, @@ -754,7 +693,136 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf, } +LV_ATTRIBUTE_FAST_MEM +static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, + const lv_draw_img_dsc_t * draw_dsc, + const lv_area_t * coords, + const uint8_t * src_buf, + lv_img_cf_t cf) +{ + /*Use the clip area as draw area*/ + lv_area_t draw_area; + lv_area_copy(&draw_area, draw_ctx->clip_area); + bool mask_any = lv_draw_mask_is_any(&draw_area); + bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; + + lv_area_t blend_area; + lv_draw_sw_blend_dsc_t blend_dsc; + + lv_memset_00(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t)); + blend_dsc.opa = draw_dsc->opa; + blend_dsc.blend_mode = draw_dsc->blend_mode; + blend_dsc.blend_area = &blend_area; + + /*The simplest case just copy the pixels into the draw_buf*/ + if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) { + blend_dsc.src_buf = (const lv_color_t *)src_buf; + + blend_dsc.blend_area = coords; + lv_draw_sw_blend(draw_ctx, &blend_dsc); + } + /*In the other cases every pixel need to be checked one-by-one*/ + else { + blend_area.x1 = draw_ctx->clip_area->x1; + blend_area.x2 = draw_ctx->clip_area->x2; + blend_area.y1 = draw_ctx->clip_area->y1; + blend_area.y2 = draw_ctx->clip_area->y2; + + lv_coord_t src_w = lv_area_get_width(coords); + lv_coord_t src_h = lv_area_get_height(coords); + lv_coord_t blend_h = lv_area_get_height(&blend_area); + lv_coord_t blend_w = lv_area_get_width(&blend_area); + + uint32_t max_buf_size = MAX_BUF_SIZE; + uint32_t blend_size = lv_area_get_size(&blend_area); + uint32_t buf_h; + uint32_t buf_w = blend_w; + if(blend_size <= max_buf_size) { + buf_h = blend_h; + } + else { + /*Round to full lines*/ + buf_h = max_buf_size / blend_w; + } + + /*Create buffers and masks*/ + uint32_t buf_size = buf_w * buf_h; + + lv_color_t * rgb_buf = lv_mem_buf_get(buf_size * sizeof(lv_color_t)); + lv_opa_t * mask_buf = lv_mem_buf_get(buf_size); + blend_dsc.mask_buf = mask_buf; + blend_dsc.mask_area = &blend_area; + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + blend_dsc.src_buf = rgb_buf; + lv_coord_t y_last = blend_area.y2; + blend_area.y2 = blend_area.y1 + buf_h - 1; + + lv_draw_mask_res_t mask_res_def = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle || + draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? + LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; + blend_dsc.mask_res = mask_res_def; + + while(blend_area.y1 <= y_last) { + /*Apply transformations if any or separate the channels*/ + lv_area_t transform_area; + lv_area_copy(&transform_area, &blend_area); + lv_area_move(&transform_area, -coords->x1, -coords->y1); + if(transform) { + lv_draw_transform(draw_ctx, &transform_area, src_buf, src_w, src_h, src_w, + draw_dsc, cf, rgb_buf, mask_buf); + } + else { + convert_cb(&transform_area, src_buf, src_w, src_h, src_w, draw_dsc, cf, rgb_buf, mask_buf); + } + + /*Apply recolor*/ + if(draw_dsc->recolor_opa > LV_OPA_MIN) { + uint16_t premult_v[3]; + lv_opa_t recolor_opa = draw_dsc->recolor_opa; + lv_color_t recolor = draw_dsc->recolor; + lv_color_premult(recolor, recolor_opa, premult_v); + uint32_t i; + for(i = 0; i < buf_size; i++) { + rgb_buf[i] = lv_color_mix_premult(premult_v, rgb_buf[i], recolor_opa); + } + } +#if LV_DRAW_COMPLEX + /*Apply the masks if any*/ + if(mask_any) { + lv_coord_t y; + lv_opa_t * mask_buf_tmp = mask_buf; + for(y = blend_area.y1; y <= blend_area.y2; y++) { + lv_draw_mask_res_t mask_res_line; + mask_res_line = lv_draw_mask_apply(mask_buf_tmp, blend_area.x1, y, blend_w); + + if(mask_res_line == LV_DRAW_MASK_RES_TRANSP) { + lv_memset_00(mask_buf_tmp, blend_w); + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + } + else if(mask_res_line == LV_DRAW_MASK_RES_CHANGED) { + blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED; + } + mask_buf_tmp += blend_w; + } + } +#endif + + /*Blend*/ + lv_draw_sw_blend(draw_ctx, &blend_dsc); + + /*Go the the next lines*/ + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1 + buf_h - 1; + if(blend_area.y2 > y_last) blend_area.y2 = y_last; + } + + lv_mem_buf_release(mask_buf); + lv_mem_buf_release(rgb_buf); + } +} + +#if 0 /* the old version, left here for reference only */ LV_ATTRIBUTE_FAST_MEM static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * draw_dsc, @@ -1027,7 +1095,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, } } } - +#endif static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) @@ -1047,6 +1115,81 @@ static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) /********************** * STATIC FUNCTIONS **********************/ +/* Separate the image channels to RGB and Alpha to match LV_COLOR_DEPTH settings*/ +static void convert_cb(const lv_area_t * dest_area, const void * src_buf, lv_coord_t src_w, lv_coord_t src_h, + lv_coord_t src_stride, const lv_draw_img_dsc_t * draw_dsc, lv_img_cf_t cf, lv_color_t * cbuf, lv_opa_t * abuf) +{ + LV_UNUSED(draw_dsc); + LV_UNUSED(src_h); + LV_UNUSED(src_w); + + const uint8_t * src_tmp8 = (const uint8_t *)src_buf; + lv_coord_t y; + lv_coord_t x; + + if(cf == LV_IMG_CF_TRUE_COLOR || cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t px_cnt = lv_area_get_size(dest_area); + lv_memset_ff(abuf, px_cnt); + + src_tmp8 += (src_stride * dest_area->y1 * sizeof(lv_color_t)) + dest_area->x1 * sizeof(lv_color_t); + uint32_t dest_w = lv_area_get_width(dest_area); + uint32_t dest_w_byte = dest_w * sizeof(lv_color_t); + + lv_coord_t src_stride_byte = src_stride * sizeof(lv_color_t); + lv_color_t * cbuf_tmp = cbuf; + for(y = dest_area->y1; y <= dest_area->y2; y++) { + lv_memcpy(cbuf_tmp, src_tmp8, dest_w_byte); + src_tmp8 += src_stride_byte; + cbuf_tmp += dest_w; + } + + /*Make "holes" for with Chroma keying*/ + if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) { + uint32_t i; + lv_color_t chk = LV_COLOR_CHROMA_KEY; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + uint8_t * cbuf_uint = (uint8_t *)cbuf; + uint8_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 16 + uint16_t * cbuf_uint = (uint16_t *)cbuf; + uint16_t chk_v = chk.full; +#elif LV_COLOR_DEPTH == 32 + uint32_t * cbuf_uint = (uint32_t *)cbuf; + uint32_t chk_v = chk.full; +#endif + for(i = 0; i < px_cnt; i++) { + if(chk_v == cbuf_uint[i]) abuf[i] = 0x00; + } + } + } + else if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) { + src_tmp8 += (src_stride * dest_area->y1 * LV_IMG_PX_SIZE_ALPHA_BYTE) + dest_area->x1 * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t src_new_line_step_px = (src_stride - lv_area_get_width(dest_area)); + lv_coord_t src_new_line_step_byte = src_new_line_step_px * LV_IMG_PX_SIZE_ALPHA_BYTE; + + lv_coord_t dest_h = lv_area_get_height(dest_area); + lv_coord_t dest_w = lv_area_get_width(dest_area); + for(y = 0; y < dest_h; y++) { + for(x = 0; x < dest_w; x++) { + abuf[x] = src_tmp8[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; +#if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 + cbuf[x].full = *src_tmp8; +#elif LV_COLOR_DEPTH == 16 + cbuf[x].full = *src_tmp8 + ((*(src_tmp8 + 1)) << 8); +#elif LV_COLOR_DEPTH == 32 + cbuf[x] = *((lv_color_t *) src_tmp8); + cbuf[x].ch.alpha = 0xff; +#endif + src_tmp8 += LV_IMG_PX_SIZE_ALPHA_BYTE; + + } + cbuf += dest_w; + abuf += dest_w; + src_tmp8 += src_new_line_step_byte; + } + } +} #if 0 static void invalidate_cache(void)