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)