fix build error and upadte lv_conf_template.h

This commit is contained in:
Gabor Kiss-Vamosi
2020-04-29 09:01:26 +02:00
22 changed files with 654 additions and 214 deletions

View File

@@ -177,6 +177,7 @@ typedef void * lv_group_user_data_t;
/* 1: Enable GPU interface*/
#define LV_USE_GPU 1
#define LV_USE_GPU_STM32_DMA2D 0
/* 1: Enable file system (might be required for images */
#define LV_USE_FILESYSTEM 1
@@ -233,6 +234,10 @@ typedef void * lv_img_decoder_user_data_t;
* font's bitmaps */
#define LV_ATTRIBUTE_LARGE_CONST
/* Prefix performance critical functions to place them into a faster memory (e.g RAM)
* Uses 15-20 kB extra memory */
#define LV_ATTRIBUTE_FAST_MEM
/* Export integer constant to binding.
* This macro is used with constants in the form of LV_<CONST> that
* should also appear on lvgl binding API such as Micropython

View File

@@ -5,5 +5,6 @@ include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_font/lv_font.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc/lv_misc.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_themes/lv_themes.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_draw/lv_draw.mk
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_gpu/lv_gpu.mk

View File

@@ -263,6 +263,9 @@
#ifndef LV_USE_GPU
#define LV_USE_GPU 1
#endif
#ifndef LV_USE_GPU_STM32_DMA2D
#define LV_USE_GPU_STM32_DMA2D 0
#endif
/* 1: Enable file system (might be required for images */
#ifndef LV_USE_FILESYSTEM
@@ -339,6 +342,12 @@
#define LV_ATTRIBUTE_LARGE_CONST
#endif
/* Prefix performance critical functions to place them into a faster memory (e.g RAM)
* Uses 15-20 kB extra memory */
#ifndef LV_ATTRIBUTE_FAST_MEM
#define LV_ATTRIBUTE_FAST_MEM
#endif
/* Export integer constant to binding.
* This macro is used with constants in the form of LV_<CONST> that
* should also appear on lvgl binding API such as Micropython

View File

@@ -458,7 +458,9 @@ static void lv_refr_area_part(const lv_area_t * area_p)
/*In non double buffered mode, before rendering the next part wait until the previous image is
* flushed*/
if(lv_disp_is_double_buf(disp_refr) == false) {
while(vdb->flushing) ;
while(vdb->flushing) {
if(disp_refr->driver.wait_cb) disp_refr->driver.wait_cb(&disp_refr->driver);
}
}
lv_obj_t * top_p;
@@ -654,7 +656,9 @@ static void lv_refr_vdb_flush(void)
/*In double buffered mode wait until the other buffer is flushed before flushing the current
* one*/
if(lv_disp_is_double_buf(disp_refr)) {
while(vdb->flushing);
while(vdb->flushing) {
if(disp_refr->driver.wait_cb) disp_refr->driver.wait_cb(&disp_refr->driver);
}
}
vdb->flushing = 1;

View File

@@ -35,7 +35,7 @@
/**********************
* STATIC PROTOTYPES
**********************/
static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop);
LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop);
static lv_style_t * get_alloc_local_style(lv_style_list_t * list);
/**********************
@@ -1015,7 +1015,7 @@ lv_res_t lv_style_list_get_ptr(lv_style_list_t * list, lv_style_property_t prop,
* E.g. `LV_STYLE_TEXT_FONT | (LV_STATE_PRESSED << LV_STYLE_STATE_POS)`
* @return
*/
static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop)
LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop)
{
LV_ASSERT_STYLE(style);

View File

@@ -12,11 +12,11 @@
#include "../lv_hal/lv_hal_disp.h"
#include "../lv_core/lv_refr.h"
#include "../lv_gpu/lv_gpu_stm32_dma2d.h"
/*********************
* DEFINES
*********************/
#define FILL_DIRECT_LEN 32
#define FILL_DIRECT_MASK 0x1F
#define GPU_SIZE_LIMIT 240
/**********************
@@ -65,8 +65,8 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co
#define FILL_NORMAL_MASK_PX(out_x, color) \
if(*mask_tmp_x) { \
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_tmp[out_x] = color; \
else disp_buf_tmp[out_x] = lv_color_mix(color, disp_buf_tmp[out_x], *mask_tmp_x); \
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[out_x] = color; \
else disp_buf_first[out_x] = lv_color_mix(color, disp_buf_first[out_x], *mask_tmp_x); \
} \
mask_tmp_x++;
@@ -83,8 +83,8 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co
#define MAP_NORMAL_MASK_PX(x) \
if(*mask_tmp_x) { \
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_tmp[x] = map_buf_tmp[x]; \
else disp_buf_tmp[x] = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], *mask_tmp_x); \
if(*mask_tmp_x == LV_OPA_COVER) disp_buf_first[x] = map_buf_first[x]; \
else disp_buf_first[x] = lv_color_mix(map_buf_first[x], disp_buf_first[x], *mask_tmp_x); \
} \
mask_tmp_x++;
@@ -103,17 +103,17 @@ mask_tmp_x++;
/**
*
* @param disp_area
* @param clip_area already truncated to disp_arae
* @param fill_area
* @param disp_buf
* @param cf
* @param color
* @param mask
* @param mask_res
* @param opa
* @param mode
* Fill and area in the display buffer.
* @param clip_area clip the fill to this area (absolute coordinates)
* @param fill_area fill this area (absolute coordinates) (should be clipped)
* @param color fill color
* @param mask a mask to apply on the fill (uint8_t array with 0x00..0xff values).
* Relative to fill area but its width is truncated to clip area.
* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),
* LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),
* LV_MASK_RES_CHANGED: the mask has mixed values
* @param opa overall opacity in 0x00..0xff range
* @param mode blend mode from `lv_blend_mode_t`
*/
LV_ATTRIBUTE_FAST_MEM void lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area,
lv_color_t color, lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_opa_t opa,
@@ -123,7 +123,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_blend_fill(const lv_area_t * clip_area, const lv_a
asd++;
/*Do not draw transparent things*/
if(opa < LV_OPA_MIN) return;
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) return;
if(mask_res == LV_DRAW_MASK_RES_TRANSP) return;
lv_disp_t * disp = lv_refr_get_disp_refreshing();
lv_disp_buf_t * vdb = lv_disp_get_buf(disp);
@@ -168,14 +168,26 @@ LV_ATTRIBUTE_FAST_MEM void lv_blend_fill(const lv_area_t * clip_area, const lv_a
}
}
/**
* Copy a map (image) to a display buffer.
* @param clip_area clip the map to this area (absolute coordinates)
* @param map_area area of the image (absolute coordinates)
* @param map_buf a pixels of the map (image)
* @param mask a mask to apply on every pixel (uint8_t array with 0x00..0xff values).
* Relative to map area but its width is truncated to clip area.
* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),
* LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),
* LV_MASK_RES_CHANGED: the mask has mixed values
* @param opa overall opacity in 0x00..0xff range
* @param mode blend mode from `lv_blend_mode_t`
*/
LV_ATTRIBUTE_FAST_MEM void lv_blend_map(const lv_area_t * clip_area, const lv_area_t * map_area, const lv_color_t * map_buf,
lv_opa_t * mask, lv_draw_mask_res_t mask_res,
lv_opa_t opa, lv_blend_mode_t mode)
{
/*Do not draw transparent things*/
if(opa < LV_OPA_MIN) return;
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) return;
if(mask_res == LV_DRAW_MASK_RES_TRANSP) return;
/* Get clipped fill area which is the real draw area.
* It is always the same or inside `fill_area` */
@@ -262,6 +274,19 @@ static void fill_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, con
}
}
/**
* Fill an area with a color
* @param disp_area the current display area (destination area)
* @param disp_buf destination buffer
* @param draw_area fill this area (relative to `disp_area`)
* @param color fill color
* @param opa overall opacity in 0x00..0xff range
* @param mask a mask to apply on every pixel (uint8_t array with 0x00..0xff values).
* It fits into draw_area.
* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),
* LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),
* LV_MASK_RES_CHANGED: the mask has mixed values
*/
LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area,
lv_color_t color, lv_opa_t opa,
const lv_opa_t * mask, lv_draw_mask_res_t mask_res)
@@ -274,11 +299,11 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
/*Get the width of the `disp_area` it will be used to go to the next line*/
int32_t disp_w = lv_area_get_width(disp_area);
/*Get the width of the `draw_area` it will be used to go to the next line of the mask*/
int32_t draw_area_w = lv_area_get_width(draw_area);
int32_t draw_area_h = lv_area_get_height(draw_area);
/*Create a temp. disp_buf which always point to current line to draw*/
lv_color_t * disp_buf_tmp = disp_buf + disp_w * draw_area->y1;
/*Create a temp. disp_buf which always point to the first pixel of the destination area*/
lv_color_t * disp_buf_first = disp_buf + disp_w * draw_area->y1 + draw_area->x1;
int32_t x;
int32_t y;
@@ -286,33 +311,22 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
/*Simple fill (maybe with opacity), no masking*/
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) {
if(opa > LV_OPA_MAX) {
lv_color_t * disp_buf_tmp_ori = disp_buf_tmp;
#if LV_USE_GPU
if(disp->driver.gpu_fill_cb && lv_area_get_size(draw_area) > GPU_SIZE_LIMIT) {
disp->driver.gpu_fill_cb(&disp->driver, disp_buf, disp_w, draw_area, color);
return;
}
#if LV_USE_GPU_STM32_DMA2D
if(lv_area_get_size(draw_area) >= 240) {
lv_gpu_stm32_dma2d_fill(disp_buf_first, disp_w, color, draw_area_w, draw_area_h);
return;
}
#endif
/*Fill the first line. Use `memcpy` because it's faster then simple value assignment*/
/*Set the first pixels manually*/
int32_t fill_end = draw_area->x1 + FILL_DIRECT_LEN + (draw_area_w & FILL_DIRECT_MASK) - 1;
int32_t direct_fill_end = LV_MATH_MIN(draw_area->x2,
fill_end);
for(x = draw_area->x1; x <= direct_fill_end ; x++) {
disp_buf_tmp[x].full = color.full;
}
for(; x <= draw_area->x2; x += FILL_DIRECT_LEN) {
lv_memcpy(&disp_buf_tmp[x], &disp_buf_tmp[draw_area->x1], FILL_DIRECT_LEN * sizeof(lv_color_t));
}
disp_buf_tmp += disp_w;
for(y = draw_area->y1 + 1; y <= draw_area->y2; y++) {
lv_memcpy(&disp_buf_tmp[draw_area->x1], &disp_buf_tmp_ori[draw_area->x1], draw_area_w * sizeof(lv_color_t));
disp_buf_tmp += disp_w;
#endif
/*Software rendering*/
for(y = 0; y < draw_area_h; y++) {
lv_color_fill(disp_buf_first, color, draw_area_w);
disp_buf_first += disp_w;
}
}
/*No mask with opacity*/
@@ -323,8 +337,8 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
for(x = 0; x < draw_area_w ; x++) blend_buf[x].full = color.full;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
disp->driver.gpu_blend_cb(&disp->driver, &disp_buf_tmp[draw_area->x1], blend_buf, draw_area_w, opa);
disp_buf_tmp += disp_w;
disp->driver.gpu_blend_cb(&disp->driver, disp_buf_first, blend_buf, draw_area_w, opa);
disp_buf_first += disp_w;
}
return;
}
@@ -336,48 +350,52 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
lv_color_premult(color, opa, color_premult);
lv_opa_t opa_inv = 255 - opa;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
for(x = draw_area->x1; x <= draw_area->x2; x++) {
if(last_dest_color.full != disp_buf_tmp[x].full) {
last_dest_color = disp_buf_tmp[x];
for(y = 0; y < draw_area_h; y++) {
for(x = 0; x < draw_area_w; x++) {
if(last_dest_color.full != disp_buf_first[x].full) {
last_dest_color = disp_buf_first[x];
#if LV_COLOR_SCREEN_TRANSP
if(disp->driver.screen_transp) {
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, color, opa, &last_res_color,
lv_color_mix_with_alpha(disp_buf_first[x], disp_buf_first[x].ch.alpha, color, opa, &last_res_color,
&last_res_color.ch.alpha);
}
else
#endif
{
last_res_color = lv_color_mix_premult(color_premult, disp_buf_tmp[x], opa_inv);
last_res_color = lv_color_mix_premult(color_premult, disp_buf_first[x], opa_inv);
}
}
disp_buf_tmp[x] = last_res_color;
disp_buf_first[x] = last_res_color;
}
disp_buf_tmp += disp_w;
disp_buf_first += disp_w;
}
}
}
/*Masked*/
else {
/* The mask is relative to the clipped area.
* In the cycles below mask will be indexed from `draw_area.x1`
* but it corresponds to zero index. So prepare `mask_tmp` accordingly. */
const lv_opa_t * mask_tmp = mask - draw_area->x1;
/*DMA2D could be used here but it's much slower than software rendering*/
#if LV_USE_GPU_STM32_DMA2D && 0
if(lv_area_get_size(draw_area) > 240) {
lv_gpu_stm32_dma2d_fill_mask(disp_buf_first, disp_w, color, mask, opa, draw_area_w, draw_area_h);
return;
}
#endif
/*Buffer the result color to avoid recalculating the same color*/
lv_color_t last_dest_color;
lv_color_t last_res_color;
lv_opa_t last_mask = LV_OPA_TRANSP;
last_dest_color.full = disp_buf_tmp[0].full;
last_res_color.full = disp_buf_tmp[0].full;
last_dest_color.full = disp_buf_first[0].full;
last_res_color.full = disp_buf_first[0].full;
int32_t x_end4 = draw_area->x2 - 4;
int32_t x_end4 = draw_area_w - 4;
/*Only the mask matters*/
if(opa > LV_OPA_MAX) {
for(y = draw_area->y1; y <= draw_area->y2; y++) {
const lv_opa_t * mask_tmp_x = &mask_tmp[draw_area->x1];
for(y = 0; y < draw_area_h; y++) {
const lv_opa_t * mask_tmp_x = mask;
#if 0
for(x = draw_area->x1; x <= draw_area->x2; x++) {
#if LV_COLOR_SCREEN_TRANSP
@@ -387,7 +405,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
#endif
}
#else
for(x = draw_area->x1; x <= draw_area->x2 && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
for(x = 0; x < draw_area_w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
#if LV_COLOR_SCREEN_TRANSP
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
#else
@@ -399,10 +417,10 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
for(; x <= x_end4; x += 4) {
if(*mask32) {
if((*mask32) == 0xFFFFFFFF) {
disp_buf_tmp[x] = color;
disp_buf_tmp[x + 1] = color;
disp_buf_tmp[x + 2] = color;
disp_buf_tmp[x + 3] = color;
disp_buf_first[x] = color;
disp_buf_first[x + 1] = color;
disp_buf_first[x + 2] = color;
disp_buf_first[x + 3] = color;
}
else {
mask_tmp_x = (const lv_opa_t *)mask32;
@@ -423,7 +441,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
}
mask_tmp_x = (const lv_opa_t *)mask32;
for(; x <= draw_area->x2 ; x++) {
for(; x < draw_area_w ; x++) {
#if LV_COLOR_SCREEN_TRANSP
FILL_NORMAL_MASK_PX_SCR_TRANSP(x, color)
#else
@@ -431,46 +449,60 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co
#endif
}
#endif
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
disp_buf_first += disp_w;
mask += draw_area_w;
}
}
/*Handle opa and mask values too*/
else {
lv_opa_t opa_tmp = LV_OPA_TRANSP;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
const lv_opa_t * mask_tmp_x = &mask_tmp[draw_area->x1];
for(x = draw_area->x1; x <= draw_area->x2; x++) {
const lv_opa_t * mask_tmp_x = mask;
for(x = 0; x < draw_area_w; x++) {
if(*mask_tmp_x) {
if(*mask_tmp_x != last_mask) opa_tmp = *mask_tmp_x == LV_OPA_COVER ? opa : (uint32_t)((uint32_t)(
*mask_tmp_x) * opa) >> 8;
if(*mask_tmp_x != last_mask || last_dest_color.full != disp_buf_tmp[x].full) {
if(*mask_tmp_x != last_mask || last_dest_color.full != disp_buf_first[x].full) {
#if LV_COLOR_SCREEN_TRANSP
if(disp->driver.screen_transp) {
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, color, opa_tmp, &last_res_color,
lv_color_mix_with_alpha(disp_buf_first[x], disp_buf_first[x].ch.alpha, color, opa_tmp, &last_res_color,
&last_res_color.ch.alpha);
}
else
#endif
{
if(opa_tmp == LV_OPA_COVER) last_res_color = color;
else last_res_color = lv_color_mix(color, disp_buf_tmp[x], opa_tmp);
else last_res_color = lv_color_mix(color, disp_buf_first[x], opa_tmp);
}
last_mask = *mask_tmp_x;
last_dest_color.full = disp_buf_tmp[x].full;
last_dest_color.full = disp_buf_first[x].full;
}
disp_buf_tmp[x] = last_res_color;
disp_buf_first[x] = last_res_color;
}
mask_tmp_x++;
}
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
disp_buf_first += disp_w;
mask += draw_area_w;
}
}
}
}
/**
* Fill an area with a color but apply blending algorithms
* @param disp_area the current display area (destination area)
* @param disp_buf destination buffer
* @param draw_area fill this area (relative to `disp_area`)
* @param color fill color
* @param opa overall opacity in 0x00..0xff range
* @param mask a mask to apply on every pixel (uint8_t array with 0x00..0xff values).
* It fits into draw_area.
* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),
* LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),
* LV_MASK_RES_CHANGED: the mask has mixed values
* @param mode blend mode from `lv_blend_mode_t`
*/
static void fill_blended(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area,
lv_color_t color, lv_opa_t opa,
const lv_opa_t * mask, lv_draw_mask_res_t mask_res, lv_blend_mode_t mode)
@@ -597,7 +629,19 @@ static void map_set_px(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
}
}
/**
* Copy an image to an area
* @param disp_area the current display area (destination area)
* @param disp_buf destination buffer
* @param map_area coordinates of the map (image) to copy. (absolute coordinates)
* @param map_buf the pixel of the image
* @param opa overall opacity in 0x00..0xff range
* @param mask a mask to apply on every pixel (uint8_t array with 0x00..0xff values).
* It fits into draw_area.
* @param mask_res LV_MASK_RES_COVER: the mask has only 0xff values (no mask),
* LV_MASK_RES_TRANSP: the mask has only 0x00 values (full transparent),
* LV_MASK_RES_CHANGED: the mask has mixed values
*/
LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, const lv_area_t * draw_area,
const lv_area_t * map_area, const lv_color_t * map_buf, lv_opa_t opa,
const lv_opa_t * mask, lv_draw_mask_res_t mask_res)
@@ -606,18 +650,18 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
/*Get the width of the `disp_area` it will be used to go to the next line*/
int32_t disp_w = lv_area_get_width(disp_area);
/*Get the width of the `draw_area` it will be used to go to the next line of the mask*/
int32_t draw_area_w = lv_area_get_width(draw_area);
int32_t draw_area_h = lv_area_get_height(draw_area);
/*Get the width of the `mask_area` it will be used to go to the next line*/
int32_t map_w = lv_area_get_width(map_area);
/*Create a temp. disp_buf which always point to current line to draw*/
lv_color_t * disp_buf_tmp = disp_buf + disp_w * draw_area->y1;
/*Create a temp. map_buf which always point to current line to draw*/
const lv_color_t * map_buf_tmp = map_buf + map_w * (draw_area->y1 - (map_area->y1 - disp_area->y1));
/*Create a temp. disp_buf which always point to first pixel to draw*/
lv_color_t * disp_buf_first = disp_buf + disp_w * draw_area->y1 + draw_area->x1;
/*Create a temp. map_buf which always point to first pixel to draw from the map*/
const lv_color_t * map_buf_first = map_buf + map_w * (draw_area->y1 - (map_area->y1 - disp_area->y1));
map_buf_first += (draw_area->x1 - (map_area->x1 - disp_area->x1));
#if LV_COLOR_SCREEN_TRANSP
lv_opa_t opa_composed;
@@ -631,70 +675,76 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
/*Simple fill (maybe with opacity), no masking*/
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) {
/*Go to the first px of the row*/
map_buf_tmp += (draw_area->x1 - (map_area->x1 - disp_area->x1));
#if LV_USE_GPU
if(disp->driver.gpu_blend_cb && (lv_area_get_size(draw_area) > GPU_SIZE_LIMIT)) {
for(y = draw_area->y1; y <= draw_area->y2; y++) {
disp->driver.gpu_blend_cb(&disp->driver, &disp_buf_tmp[draw_area->x1], map_buf_tmp, draw_area_w, opa);
disp_buf_tmp += disp_w;
map_buf_tmp += map_w;
disp->driver.gpu_blend_cb(&disp->driver, disp_buf_first, map_buf_first, draw_area_w, opa);
disp_buf_first += disp_w;
map_buf_first += map_w;
}
return;
}
#endif
if(opa > LV_OPA_MAX) {
for(y = draw_area->y1; y <= draw_area->y2; y++) {
lv_memcpy(&disp_buf_tmp[draw_area->x1], map_buf_tmp, draw_area_w * sizeof(lv_color_t));
disp_buf_tmp += disp_w;
map_buf_tmp += map_w;
#if LV_USE_GPU_STM32_DMA2D
if(lv_area_get_size(draw_area) >= 240) {
lv_gpu_stm32_dma2d_copy(disp_buf_first, disp_w, map_buf_first, map_w, draw_area_w, draw_area_h);
return;
}
#endif
/*Software rendering*/
for(y = 0; y < draw_area_h; y++) {
lv_memcpy(disp_buf_first, map_buf_first, draw_area_w * sizeof(lv_color_t));
disp_buf_first += disp_w;
map_buf_first += map_w;
}
}
else {
/*The map will be indexed from `draw_area->x1` so compensate it.*/
map_buf_tmp -= draw_area->x1;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
for(x = draw_area->x1; x <= draw_area->x2; x++) {
#if LV_USE_GPU_STM32_DMA2D
if(lv_area_get_size(draw_area) >= 240) {
lv_gpu_stm32_dma2d_blend(disp_buf_first, disp_w, map_buf_first, opa, map_w, draw_area_w, draw_area_h);
return;
}
#endif
/*Software rendering*/
for(y = 0; y < draw_area_h; y++) {
for(x = 0; x < draw_area_w; x++) {
#if LV_COLOR_SCREEN_TRANSP
if(disp->driver.screen_transp) {
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, map_buf_tmp[x], opa, &disp_buf_tmp[x],
&disp_buf_tmp[x].ch.alpha);
lv_color_mix_with_alpha(disp_buf_first[x], disp_buf_first[x].ch.alpha, map_buf_first[x], opa, &disp_buf_first[x],
&disp_buf_first[x].ch.alpha);
}
else
#endif
{
disp_buf_tmp[x] = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], opa);
disp_buf_first[x] = lv_color_mix(map_buf_first[x], disp_buf_first[x], opa);
}
}
disp_buf_tmp += disp_w;
map_buf_tmp += map_w;
disp_buf_first += disp_w;
map_buf_first += map_w;
}
}
}
/*Masked*/
else {
/* The mask is relative to the clipped area.
* In the cycles below mask will be indexed from `draw_area.x1`
* but it corresponds to zero index. So prepare `mask_tmp` accordingly. */
const lv_opa_t * mask_tmp = mask - draw_area->x1;
/*Only the mask matters*/
if(opa > LV_OPA_MAX) {
/*Go to the first pixel of the row */
map_buf_tmp += (draw_area->x1 - (map_area->x1 - disp_area->x1));
map_buf_tmp -= draw_area->x1;
int32_t x_end4 = draw_area->x2 - 4;
int32_t x_end4 = draw_area_w - 4;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
const lv_opa_t * mask_tmp_x = &mask_tmp[draw_area->x1];
for(y = 0; y < draw_area_h; y++) {
const lv_opa_t * mask_tmp_x = mask;
#if 0
for(x = draw_area->x1; x <= draw_area->x2; x++) {
MAP_NORMAL_MASK_PX(x);
}
#else
for(x = draw_area->x1; x <= draw_area->x2 && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
for(x = 0; x < draw_area_w && ((lv_uintptr_t)mask_tmp_x & 0x3); x++) {
#if LV_COLOR_SCREEN_TRANSP
MAP_NORMAL_MASK_PX_SCR_TRANSP(x)
#else
@@ -703,13 +753,13 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
}
uint32_t * mask32 = (uint32_t *) mask_tmp_x;
for(; x <= x_end4; x += 4) {
for(; x < x_end4; x += 4) {
if(*mask32) {
if((*mask32) == 0xFFFFFFFF) {
disp_buf_tmp[x] = map_buf_tmp[x];
disp_buf_tmp[x + 1] = map_buf_tmp[x + 1];
disp_buf_tmp[x + 2] = map_buf_tmp[x + 2];
disp_buf_tmp[x + 3] = map_buf_tmp[x + 3];
disp_buf_first[x] = map_buf_first[x];
disp_buf_first[x + 1] = map_buf_first[x + 1];
disp_buf_first[x + 2] = map_buf_first[x + 2];
disp_buf_first[x + 3] = map_buf_first[x + 3];
}
else {
mask_tmp_x = (const lv_opa_t *)mask32;
@@ -730,7 +780,7 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
}
mask_tmp_x = (const lv_opa_t *)mask32;
for(; x <= draw_area->x2 ; x++) {
for(; x < draw_area_w ; x++) {
#if LV_COLOR_SCREEN_TRANSP
MAP_NORMAL_MASK_PX_SCR_TRANSP(x)
#else
@@ -738,33 +788,32 @@ LV_ATTRIBUTE_FAST_MEM static void map_normal(const lv_area_t * disp_area, lv_col
#endif
}
#endif
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
map_buf_tmp += map_w;
disp_buf_first += disp_w;
mask += draw_area_w;
map_buf_first += map_w;
}
}
/*Handle opa and mask values too*/
else {
map_buf_tmp -= draw_area->x1;
for(y = draw_area->y1; y <= draw_area->y2; y++) {
for(x = draw_area->x1; x <= draw_area->x2; x++) {
if(mask_tmp[x]) {
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[x]) >> 8);
for(y = 0; y < draw_area_h; y++) {
for(x = 0; x < draw_area_w; x++) {
if(mask[x]) {
lv_opa_t opa_tmp = mask[x] >= LV_OPA_MAX ? opa : ((opa * mask[x]) >> 8);
#if LV_COLOR_SCREEN_TRANSP
if(disp->driver.screen_transp) {
lv_color_mix_with_alpha(disp_buf_tmp[x], disp_buf_tmp[x].ch.alpha, map_buf_tmp[x], opa_tmp, &disp_buf_tmp[x],
&disp_buf_tmp[x].ch.alpha);
lv_color_mix_with_alpha(disp_buf_first[x], disp_buf_first[x].ch.alpha, map_buf_first[x], opa_tmp, &disp_buf_first[x],
&disp_buf_first[x].ch.alpha);
}
else
#endif
{
disp_buf_tmp[x] = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
disp_buf_first[x] = lv_color_mix(map_buf_first[x], disp_buf_first[x], opa_tmp);
}
}
}
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
map_buf_tmp += map_w;
disp_buf_first += disp_w;
mask += draw_area_w;
map_buf_first += map_w;
}
}
}

View File

@@ -13,6 +13,8 @@
#include "../lv_core/lv_refr.h"
#include "../lv_misc/lv_mem.h"
#include "../lv_misc/lv_math.h"
#include "../lv_gpu/lv_gpu_stm32_dma2d.h"
/*********************
* DEFINES
@@ -395,6 +397,16 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const
/*Simple ARGB image. Handle it as special case because it's very common*/
if(other_mask_cnt == 0 && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) {
#if LV_USE_GPU_STM32_DMA2D && LV_COLOR_DEPTH == 32
/*Blend ARGB images directly*/
if(lv_area_get_size(&draw_area) > 240) {
int32_t disp_w = lv_area_get_width(disp_area);
lv_color_t * disp_buf = vdb->buf_act;
lv_color_t * disp_buf_first = disp_buf + disp_w * draw_area.y1 + draw_area.x1;
lv_gpu_stm32_dma2d_blend(disp_buf_first, disp_w, (const lv_color_t *)map_buf_tmp, draw_dsc->opa, map_w, draw_area_w, draw_area_h);
return;
}
#endif
int32_t x;
int32_t y;
for(y = 0; y < draw_area_h; y++) {
@@ -537,7 +549,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const
lv_draw_mask_res_t mask_res_sub;
mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + vdb->area.x1, y + draw_area.y1 + vdb->area.y1,
lv_area_get_width(&draw_area));
if(mask_res_sub == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + px_i_start, lv_area_get_width(&draw_area));
mask_res = LV_DRAW_MASK_RES_CHANGED;
}

View File

@@ -562,7 +562,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_
if(other_mask_cnt) {
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2,
lv_area_get_width(&fill_area));
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&fill_area));
}
}
@@ -762,7 +762,7 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_
if(other_mask_cnt) {
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2,
lv_area_get_width(&map_area));
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + mask_p_start, lv_area_get_width(&map_area));
}
}

View File

@@ -182,7 +182,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
if(dashed) {
if(mask_res != LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res != LV_DRAW_MASK_RES_TRANSP) {
lv_style_int_t dash_cnt = dash_start;
uint32_t i;
for(i = 0; i < draw_area_w; i++, dash_cnt++) {
@@ -285,9 +285,9 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf, vdb->area.x1 + draw_area.x1, vdb->area.y1 + h, draw_area_w);
if(dashed) {
if(mask_res != LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res != LV_DRAW_MASK_RES_TRANSP) {
if(dash_cnt > dsc->dash_width) {
mask_res = LV_DRAW_MASK_RES_FULL_TRANSP;
mask_res = LV_DRAW_MASK_RES_TRANSP;
}
if(dash_cnt >= dsc->dash_gap + dsc->dash_width) {
@@ -437,7 +437,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_skew(const lv_point_t * point1, cons
for(h = draw_area.y1 + disp_area->y1; h <= draw_area.y2 + disp_area->y1; h++) {
lv_draw_mask_res_t mask_res = lv_draw_mask_apply(&mask_buf[mask_p], x, h, draw_area_w);
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(&mask_buf[mask_p], draw_area_w);
}

View File

@@ -31,24 +31,24 @@ typedef struct {
/**********************
* STATIC PROTOTYPES
**********************/
static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_radius_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_angle_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_fade_param_t * param);
static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_map_param_t * param);
static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * p);
static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * p);
static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x);
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new);
LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x);
/**********************
* STATIC VARIABLES
@@ -99,7 +99,7 @@ int16_t lv_draw_mask_add(void * param, void * custom_id)
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
*/
lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len)
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len)
{
bool changed = false;
lv_draw_mask_common_dsc_t * dsc;
@@ -110,7 +110,7 @@ lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_
dsc = m->param;
lv_draw_mask_res_t res = LV_DRAW_MASK_RES_FULL_COVER;
res = dsc->cb(mask_buf, abs_x, abs_y, len, (void *)m->param);
if(res == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(res == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP;
else if(res == LV_DRAW_MASK_RES_CHANGED) changed = true;
m++;
@@ -162,7 +162,7 @@ void * lv_draw_mask_remove_custom(void * custom_id)
* Count the currently added masks
* @return number of active masks
*/
uint8_t lv_draw_mask_get_cnt(void)
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void)
{
uint8_t cnt = 0;
uint8_t i;
@@ -425,7 +425,7 @@ void lv_draw_mask_map_init(lv_draw_mask_map_param_t * param, const lv_area_t * c
* STATIC FUNCTIONS
**********************/
static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * p)
{
/*Make to points relative to the vertex*/
@@ -442,7 +442,7 @@ static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_
else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_TOP && abs_y + 1 < 0) return LV_DRAW_MASK_RES_FULL_COVER;
else if(p->cfg.side == LV_DRAW_MASK_LINE_SIDE_BOTTOM && abs_y > 0) return LV_DRAW_MASK_RES_FULL_COVER;
else {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
}
/*Vertical*/
@@ -455,17 +455,17 @@ static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_
if(abs_x + len < 0) return LV_DRAW_MASK_RES_FULL_COVER;
else {
int32_t k = - abs_x;
if(k < 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(k < 0) return LV_DRAW_MASK_RES_TRANSP;
if(k >= 0 && k < len) lv_memset_00(&mask_buf[k], len - k);
return LV_DRAW_MASK_RES_CHANGED;
}
}
else {
if(abs_x + len < 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(abs_x + len < 0) return LV_DRAW_MASK_RES_TRANSP;
else {
int32_t k = - abs_x;
if(k < 0) k = 0;
if(k >= len) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(k >= len) return LV_DRAW_MASK_RES_TRANSP;
else if(k >= 0 && k < len) lv_memset_00(&mask_buf[0], k);
return LV_DRAW_MASK_RES_CHANGED;
}
@@ -484,7 +484,7 @@ static lv_draw_mask_res_t lv_draw_mask_line(lv_opa_t * mask_buf, lv_coord_t abs_
return res;
}
static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * p)
{
int32_t y_at_x;
@@ -496,7 +496,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
return LV_DRAW_MASK_RES_FULL_COVER;
}
else {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
}
}
@@ -506,7 +506,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
return LV_DRAW_MASK_RES_FULL_COVER;
}
else {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
}
}
@@ -517,7 +517,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
if(p->yx_steep > 0) {
if(y_at_x < abs_y) {
if(p->inv) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
else {
return LV_DRAW_MASK_RES_FULL_COVER;
@@ -527,7 +527,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
else {
if(y_at_x > abs_y) {
if(p->inv) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
else {
return LV_DRAW_MASK_RES_FULL_COVER;
@@ -581,7 +581,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
if(p->inv) {
k = xei - abs_x;
if(k > len) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(k >= 0) {
lv_memset_00(&mask_buf[0], k);
@@ -590,7 +590,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
else {
k++;
if(k < 0) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(k <= len) {
lv_memset_00(&mask_buf[k], len - k);
@@ -600,7 +600,7 @@ static lv_draw_mask_res_t line_mask_flat(lv_opa_t * mask_buf, lv_coord_t abs_x,
return LV_DRAW_MASK_RES_CHANGED;
}
static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_line_param_t * p)
{
int32_t k;
@@ -614,7 +614,7 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
return LV_DRAW_MASK_RES_FULL_COVER;
}
else {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
}
@@ -623,7 +623,7 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
x_at_y = (int32_t)((int32_t)p->xy_steep * (abs_y)) >> 10;
if(x_at_y > abs_x + len) {
if(p->inv) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
else {
return LV_DRAW_MASK_RES_FULL_COVER;
@@ -660,14 +660,14 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
if(p->inv) {
k = xsi - abs_x;
if(k >= len) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(k >= 0) lv_memset_00(&mask_buf[0], k);
}
else {
if(k > len) k = len;
if(k == 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(k == 0) return LV_DRAW_MASK_RES_TRANSP;
else if(k > 0) lv_memset_00(&mask_buf[k], len - k);
}
@@ -726,13 +726,13 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
if(p->inv) {
k = xsi - abs_x;
if(k > len) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(k > len) return LV_DRAW_MASK_RES_TRANSP;
if(k >= 0) lv_memset_00(&mask_buf[0], k);
}
else {
if(k > len) k = len;
if(k == 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(k == 0) return LV_DRAW_MASK_RES_TRANSP;
else if(k > 0) lv_memset_00(&mask_buf[k], len - k);
}
}
@@ -742,7 +742,7 @@ static lv_draw_mask_res_t line_mask_steep(lv_opa_t * mask_buf, lv_coord_t abs_x,
}
static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_angle_param_t * p)
{
int32_t rel_y = abs_y - p->cfg.vertex_p.y;
@@ -781,7 +781,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len;
if(tmp > 0) {
res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, &p->start_line);
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(res1 == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(&mask_buf[0], tmp);
}
}
@@ -789,7 +789,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len;
if(tmp < 0) tmp = 0;
res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, &p->end_line);
if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(res2 == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(&mask_buf[tmp], len - tmp);
}
if(res1 == res2) return res1;
@@ -823,7 +823,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len;
if(tmp > 0) {
res1 = lv_draw_mask_line(&mask_buf[0], abs_x, abs_y, tmp, (lv_draw_mask_line_param_t *)&p->end_line);
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(res1 == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(&mask_buf[0], tmp);
}
}
@@ -831,7 +831,7 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
if(tmp > len) tmp = len;
if(tmp < 0) tmp = 0;
res2 = lv_draw_mask_line(&mask_buf[tmp], abs_x + tmp, abs_y, len - tmp, (lv_draw_mask_line_param_t *)&p->start_line);
if(res2 == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(res2 == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(&mask_buf[tmp], len - tmp);
}
if(res1 == res2) return res1;
@@ -874,14 +874,14 @@ static lv_draw_mask_res_t lv_draw_mask_angle(lv_opa_t * mask_buf, lv_coord_t abs
res2 = lv_draw_mask_line(mask_buf, abs_x, abs_y, len, &p->end_line);
}
if(res1 == LV_DRAW_MASK_RES_FULL_TRANSP || res2 == LV_DRAW_MASK_RES_FULL_TRANSP) return LV_DRAW_MASK_RES_FULL_TRANSP;
else if(res1 == LV_DRAW_MASK_RES_UNKNOWN && res2 == LV_DRAW_MASK_RES_UNKNOWN) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(res1 == LV_DRAW_MASK_RES_TRANSP || res2 == LV_DRAW_MASK_RES_TRANSP) return LV_DRAW_MASK_RES_TRANSP;
else if(res1 == LV_DRAW_MASK_RES_UNKNOWN && res2 == LV_DRAW_MASK_RES_UNKNOWN) return LV_DRAW_MASK_RES_TRANSP;
else if(res1 == LV_DRAW_MASK_RES_FULL_COVER && res2 == LV_DRAW_MASK_RES_FULL_COVER) return LV_DRAW_MASK_RES_FULL_COVER;
else return LV_DRAW_MASK_RES_CHANGED;
}
}
static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_radius_param_t * p)
{
bool outer = p->cfg.outer;
@@ -891,7 +891,7 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
if(outer == false) {
if(abs_y < rect.y1 || abs_y >rect.y2) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
}
else {
@@ -905,13 +905,13 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
if(outer == false) {
/*Remove the edges*/
int32_t last = rect.x1 - abs_x;
if(last > len) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(last > len) return LV_DRAW_MASK_RES_TRANSP;
if(last >= 0) {
lv_memset_00(&mask_buf[0], last);
}
int32_t first = rect.x2 - abs_x + 1;
if(first <= 0) return LV_DRAW_MASK_RES_FULL_TRANSP;
if(first <= 0) return LV_DRAW_MASK_RES_TRANSP;
else if(first < len) {
lv_memset_00(&mask_buf[first], len - first);
}
@@ -1018,13 +1018,13 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
if(outer == false) {
kr++;
if(kl > len) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(kl >= 0) {
lv_memset_00(&mask_buf[0], kl);
}
if(kr < 0) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(kr <= len) {
lv_memset_00(&mask_buf[kr], len - kr);
@@ -1114,12 +1114,12 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
if(outer == 0) {
kl++;
if(kl > len) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(kl >= 0) lv_memset_00(&mask_buf[0], kl);
if(kr < 0) {
return LV_DRAW_MASK_RES_FULL_TRANSP;
return LV_DRAW_MASK_RES_TRANSP;
}
if(kr < len) lv_memset_00(&mask_buf[kr], len - kr);
}
@@ -1130,7 +1130,7 @@ static lv_draw_mask_res_t lv_draw_mask_radius(lv_opa_t * mask_buf, lv_coord_t ab
}
static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_fade_param_t * p)
{
if(abs_y < p->cfg.coords.y1) return LV_DRAW_MASK_RES_FULL_COVER;
@@ -1175,7 +1175,7 @@ static lv_draw_mask_res_t lv_draw_mask_fade(lv_opa_t * mask_buf, lv_coord_t abs_
}
}
static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
LV_ATTRIBUTE_FAST_MEM static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len,
lv_draw_mask_map_param_t * p)
{
/*Handle out of the mask cases*/
@@ -1210,7 +1210,7 @@ static lv_draw_mask_res_t lv_draw_mask_map(lv_opa_t * mask_buf, lv_coord_t abs_x
}
static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)
LV_ATTRIBUTE_FAST_MEM static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)
{
if(mask_new >= LV_OPA_MAX) return mask_act;
if(mask_new <= LV_OPA_MIN) return 0;
@@ -1224,7 +1224,7 @@ static inline lv_opa_t mask_mix(lv_opa_t mask_act, lv_opa_t mask_new)
* @param ref the reference point (already calculated sqrt)
* @param x the value which sqrt should be approximated
*/
static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x)
LV_ATTRIBUTE_FAST_MEM static inline void sqrt_approx(lv_sqrt_res_t * q, lv_sqrt_res_t * ref, uint32_t x)
{
x = x << 8; /*Upscale for extra precision*/

View File

@@ -27,7 +27,7 @@ extern "C" {
**********************/
enum {
LV_DRAW_MASK_RES_FULL_TRANSP,
LV_DRAW_MASK_RES_TRANSP,
LV_DRAW_MASK_RES_FULL_COVER,
LV_DRAW_MASK_RES_CHANGED,
LV_DRAW_MASK_RES_UNKNOWN
@@ -183,7 +183,7 @@ int16_t lv_draw_mask_add(void * param, void * custom_id);
* - `LV_DRAW_MASK_RES_FULL_COVER`: the whole line is fully visible. `mask_buf` is unchanged
* - `LV_DRAW_MASK_RES_CHANGED`: `mask_buf` has changed, it shows the desired opacity of each pixel in the given line
*/
lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len);
LV_ATTRIBUTE_FAST_MEM lv_draw_mask_res_t lv_draw_mask_apply(lv_opa_t * mask_buf, lv_coord_t abs_x, lv_coord_t abs_y, lv_coord_t len);
/**
* Remove a mask with a given ID
@@ -205,7 +205,7 @@ void * lv_draw_mask_remove_custom(void * custom_id);
* Count the currently added masks
* @return number of active masks
*/
uint8_t lv_draw_mask_get_cnt(void);
LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void);
/**
*Initialize a line mask from two points.

View File

@@ -1070,7 +1070,7 @@ LV_ATTRIBUTE_FAST_MEM static void shadow_draw_corner_buf(const lv_area_t * coord
for(y = 0; y < size; y++) {
lv_memset_ff(mask_line, size);
lv_draw_mask_res_t mask_res = mask_param.dsc.cb(mask_line, 0, y, size, &mask_param);
if(mask_res == LV_DRAW_MASK_RES_FULL_TRANSP) {
if(mask_res == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(sh_ups_tmp_buf, size * sizeof(sh_ups_tmp_buf[0]));
}
else {

6
src/lv_gpu/lv_draw.mk Normal file
View File

@@ -0,0 +1,6 @@
CSRCS += lv_gpu_stm32_dma2d.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_gpu
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_gpu
CFLAGS += "-I$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_gpu"

View File

@@ -0,0 +1,227 @@
/**
* @file lv_gpu_stm32_dma2d.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_gpu_stm32_dma2d.h"
#include "../lv_core/lv_refr.h"
#if LV_USE_GPU_STM32_DMA2D
#include "stm32f7xx_hal.h"
/*********************
* DEFINES
*********************/
#if LV_COLOR_16_SWAP
#error "Can't use DMA2D with LV_COLOR_16_SWAP 1"
#endif
#if LV_COLOR_DEPTH == 8
#error "Can't use DMA2D with LV_COLOR_DEPTH == 8"
#endif
#if LV_COLOR_DEPTH == 16
#define DMA2D_OUTPUT_FORMAT DMA2D_OUTPUT_RGB565
#define DMA2D_INPUT_FORMAT DMA2D_INPUT_RGB565
#elif LV_COLOR_DEPTH == 32
#define DMA2D_OUTPUT_FORMAT DMA2D_OUTPUT_ARGB8888
#define DMA2D_INPUT_FORMAT DMA2D_INPUT_ARGB8888
#else
/*Can't use GPU with other formats*/
#endif
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
static void invalidate_cache(void);
static void dma2d_wait(void);
/**********************
* STATIC VARIABLES
**********************/
static DMA2D_HandleTypeDef hdma2d;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Fill an area in the buffer with a color
* @param buf a buffer which should be filled
* @param buf_w width of the buffer in pixels
* @param color fill color
* @param fill_w width to fill in pixels (<= buf_w)
* @param fill_h height to fill in pixels
* @note `buf_w - fill_w` is offset to the next line after fill
*/
void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t color, lv_coord_t fill_w, lv_coord_t fill_h)
{
invalidate_cache();
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_R2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
hdma2d.Init.OutputOffset = buf_w - fill_w;
hdma2d.LayerCfg[1].InputAlpha = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
hdma2d.LayerCfg[1].InputOffset = 0;
/* DMA2D Initialization */
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_Start(&hdma2d, (uint32_t)lv_color_to32(color), (uint32_t)buf, fill_w, fill_h);
dma2d_wait();
}
/**
* Fill an area in the buffer with a color but take into account a mask which describes the opacity of each pixel
* @param buf a buffer which should be filled using a mask
* @param buf_w width of the buffer in pixels
* @param color fill color
* @param mask 0..255 values describing the opacity of the corresponding pixel. It's width is `fill_w`
* @param opa overall opacity. 255 in `mask` should mean this opacity.
* @param fill_w width to fill in pixels (<= buf_w)
* @param fill_h height to fill in pixels
* @note `buf_w - fill_w` is offset to the next line after fill
*/
void lv_gpu_stm32_dma2d_fill_mask(lv_color_t * buf, lv_coord_t buf_w, lv_color_t color, const lv_opa_t * mask, lv_opa_t opa, lv_coord_t fill_w, lv_coord_t fill_h)
{
invalidate_cache();
/* Configure the DMA2D Mode, Color Mode and line output offset */
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
hdma2d.Init.OutputOffset = buf_w - fill_w;
/* Configure the foreground -> The character */
lv_color32_t c32;
c32.full = lv_color_to32(color);
c32.ch.alpha = opa;
hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = c32.full;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_A8;
hdma2d.LayerCfg[1].InputOffset = 0;
/* Configure the background -> Display buffer */
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[0].InputAlpha = 0x00;
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_FORMAT;
hdma2d.LayerCfg[0].InputOffset = buf_w - fill_w;
/* DMA2D Initialization */
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t) mask, (uint32_t) buf, (uint32_t)buf, fill_w, fill_h);
dma2d_wait();
}
/**
* Copy a map (typically RGB image) to a buffer
* @param buf a buffer where map should be copied
* @param buf_w width of the buffer in pixels
* @param map an "image" to copy
* @param map_w width of teh map in pixels
* @param copy_w width of the area to copy in pixels (<= buf_w)
* @param copy_h height of the area to copy in pixels
* @note `map_w - fill_w` is offset to the next line after copy
*/
void lv_gpu_stm32_dma2d_copy(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_coord_t copy_w, lv_coord_t copy_h)
{
invalidate_cache();
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
hdma2d.Init.OutputOffset = buf_w - copy_w;
/* Foreground layer */
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = 0xFF;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
hdma2d.LayerCfg[1].InputOffset = map_w - copy_w;
hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
/* DMA2D Initialization */
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_Start(&hdma2d, (uint32_t)map, (uint32_t)buf, copy_w, copy_h);
dma2d_wait();
}
/**
* Blend a map (e.g. ARGB image or RGB image with opacity) to a buffer
* @param buf a buffer where `map` should be copied
* @param buf_w width of the buffer in pixels
* @param map an "image" to copy
* @param opa opacity of `map`
* @param map_w width of teh map in pixels
* @param copy_w width of the area to copy in pixels (<= buf_w)
* @param copy_h height of the area to copy in pixels
* @note `map_w - fill_w` is offset to the next line after copy
*/
void lv_gpu_stm32_dma2d_blend(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_opa_t opa, lv_coord_t map_w, lv_coord_t copy_w, lv_coord_t copy_h)
{
invalidate_cache();
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
hdma2d.Init.OutputOffset = buf_w - copy_w;
/* Background layer */
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_FORMAT;
hdma2d.LayerCfg[0].InputOffset = buf_w - copy_w;
hdma2d.LayerCfg[0].AlphaInverted = DMA2D_REGULAR_ALPHA;
/* Foreground layer */
hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = opa;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
hdma2d.LayerCfg[1].InputOffset = map_w - copy_w;
hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
/* DMA2D Initialization */
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t)map, (uint32_t)buf, (uint32_t)buf, copy_w, copy_h);
dma2d_wait();
}
/**********************
* STATIC FUNCTIONS
**********************/
static void invalidate_cache(void)
{
#if __DCACHE_PRESENT
if(SCB->CCR & (uint32_t)SCB_CCR_DC_Msk) {
SCB_CleanInvalidateDCache();
}
#endif
}
static void dma2d_wait(void)
{
lv_disp_t * disp = lv_refr_get_disp_refreshing();
while(HAL_DMA2D_PollForTransfer(&hdma2d, 0) == HAL_TIMEOUT) {
if(disp->driver.wait_cb) disp->driver.wait_cb(&disp->driver);
}
}
#endif

View File

@@ -0,0 +1,87 @@
/**
* @file lv_gpu_stm32_dma2d.h
*
*/
#ifndef LV_GPU_STM32_DMA2D_H
#define LV_GPU_STM32_DMA2D_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_misc/lv_area.h"
#include "../lv_misc/lv_color.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Fill an area in the buffer with a color
* @param buf a buffer which should be filled
* @param buf_w width of the buffer in pixels
* @param color fill color
* @param fill_w width to fill in pixels (<= buf_w)
* @param fill_h height to fill in pixels
* @note `buf_w - fill_w` is offset to the next line after fill
*/
void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t color, lv_coord_t fill_w, lv_coord_t fill_h);
/**
* Fill an area in the buffer with a color but take into account a mask which describes the opacity of each pixel
* @param buf a buffer which should be filled using a mask
* @param buf_w width of the buffer in pixels
* @param color fill color
* @param mask 0..255 values describing the opacity of the corresponding pixel. It's width is `fill_w`
* @param opa overall opacity. 255 in `mask` should mean this opacity.
* @param fill_w width to fill in pixels (<= buf_w)
* @param fill_h height to fill in pixels
* @note `buf_w - fill_w` is offset to the next line after fill
*/
void lv_gpu_stm32_dma2d_fill_mask(lv_color_t * buf, lv_coord_t buf_w, lv_color_t color, const lv_opa_t * mask, lv_opa_t opa, lv_coord_t fill_w, lv_coord_t fill_h);
/**
* Copy a map (typically RGB image) to a buffer
* @param buf a buffer where map should be copied
* @param buf_w width of the buffer in pixels
* @param map an "image" to copy
* @param map_w width of teh map in pixels
* @param copy_w width of the area to copy in pixels (<= buf_w)
* @param copy_h height of the area to copy in pixels
* @note `map_w - fill_w` is offset to the next line after copy
*/
void lv_gpu_stm32_dma2d_copy(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_coord_t map_w, lv_coord_t copy_w, lv_coord_t copy_h);
/**
* Blend a map (e.g. ARGB image or RGB image with opacity) to a buffer
* @param buf a buffer where `map` should be copied
* @param buf_w width of the buffer in pixels
* @param map an "image" to copy
* @param opa opacity of `map`
* @param map_w width of teh map in pixels
* @param copy_w width of the area to copy in pixels (<= buf_w)
* @param copy_h height of the area to copy in pixels
* @note `map_w - fill_w` is offset to the next line after copy
*/
void lv_gpu_stm32_dma2d_blend(lv_color_t * buf, lv_coord_t buf_w, const lv_color_t * map, lv_opa_t opa, lv_coord_t map_w, lv_coord_t copy_w, lv_coord_t copy_h);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_GPU_STM32_DMA2D_H*/

View File

@@ -104,6 +104,11 @@ typedef struct _disp_drv_t {
* number of flushed pixels */
void (*monitor_cb)(struct _disp_drv_t * disp_drv, uint32_t time, uint32_t px);
/** OPTIONAL: Called periodically while lvgl waits for operation to be completed.
* For example flushing or GPU
* User can execute very simple tasks here or yield the task */
void (*wait_cb)(struct _disp_drv_t * disp_drv);
#if LV_USE_GPU
/** OPTIONAL: Blend two memories using opacity (GPU only)*/
void (*gpu_blend_cb)(struct _disp_drv_t * disp_drv, lv_color_t * dest, const lv_color_t * src, uint32_t length,

View File

@@ -37,6 +37,38 @@
* STATIC FUNCTIONS
**********************/
LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num)
{
while(px_num > 16) {
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
*buf = color; buf++;
px_num -= 16;
}
while(px_num ) {
*buf = color; buf++;
px_num --;
}
}
lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl)
{
return lv_color_mix(LV_COLOR_WHITE, c, lvl);

View File

@@ -601,6 +601,8 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
(uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
}
LV_ATTRIBUTE_FAST_MEM void lv_color_fill(lv_color_t * buf, lv_color_t color, uint32_t px_num);
lv_color_t lv_color_lighten(lv_color_t c, lv_opa_t lvl);
lv_color_t lv_color_darken(lv_color_t c, lv_opa_t lvl);

View File

@@ -50,7 +50,7 @@ static const int16_t sin0_90_table[] = {
* @param angle
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
*/
int16_t lv_trigo_sin(int16_t angle)
LV_ATTRIBUTE_FAST_MEM int16_t lv_trigo_sin(int16_t angle)
{
int16_t ret = 0;
angle = angle % 360;
@@ -111,7 +111,7 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
* If root < 256: mask = 0x800
* Else: mask = 0x8000
*/
void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask)
LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask)
{
x = x << 8; /*To get 4 bit precision. (sqrt(256) = 16 = 4 bit)*/

View File

@@ -13,6 +13,7 @@ extern "C" {
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#include <stdint.h>
/*********************
@@ -62,7 +63,7 @@ typedef struct {
* @param angle
* @return sinus of 'angle'. sin(-90) = -32767, sin(90) = 32767
*/
int16_t lv_trigo_sin(int16_t angle);
LV_ATTRIBUTE_FAST_MEM int16_t lv_trigo_sin(int16_t angle);
/**
* Calculate a value of a Cubic Bezier function.
@@ -93,7 +94,7 @@ uint16_t lv_atan2(int x, int y);
* If root < 256: mask = 0x800
* Else: mask = 0x8000
*/
void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask);
LV_ATTRIBUTE_FAST_MEM void lv_sqrt(uint32_t x, lv_sqrt_res_t * q, uint32_t mask);
/**********************
* MACROS

View File

@@ -537,7 +537,7 @@ void lv_mem_buf_free_all(void)
* @param src pointer to the source buffer
* @param len number of byte to copy
*/
void * lv_memcpy(void * dst, const void * src, size_t len)
LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len)
{
uint8_t * d8 = dst;
const uint8_t * s8 = src;
@@ -602,7 +602,7 @@ void * lv_memcpy(void * dst, const void * src, size_t len)
* @param v value to set [0..255]
* @param len number of byte to set
*/
void lv_memset(void * dst, uint8_t v, size_t len)
LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len)
{
uint8_t * d8 = (uint8_t *) dst;
@@ -656,7 +656,7 @@ void lv_memset(void * dst, uint8_t v, size_t len)
* @param dst pointer to the destination buffer
* @param len number of byte to set
*/
void lv_memset_00(void * dst, size_t len)
LV_ATTRIBUTE_FAST_MEM void lv_memset_00(void * dst, size_t len)
{
uint8_t * d8 = (uint8_t *) dst;
uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;
@@ -706,7 +706,7 @@ void lv_memset_00(void * dst, size_t len)
* @param dst pointer to the destination buffer
* @param len number of byte to set
*/
void lv_memset_ff(void * dst, size_t len)
LV_ATTRIBUTE_FAST_MEM void lv_memset_ff(void * dst, size_t len)
{
uint8_t * d8 = (uint8_t *) dst;
uintptr_t d_align = (lv_uintptr_t) d8 & ALIGN_MASK;

View File

@@ -139,7 +139,7 @@ void lv_mem_buf_free_all(void);
* @param src pointer to the source buffer
* @param len number of byte to copy
*/
void * lv_memcpy(void * dst, const void * src, size_t len);
LV_ATTRIBUTE_FAST_MEM void * lv_memcpy(void * dst, const void * src, size_t len);
/**
* Same as `memcpy` but optimized to copy only a few bytes.
@@ -147,7 +147,7 @@ void * lv_memcpy(void * dst, const void * src, size_t len);
* @param src pointer to the source buffer
* @param len number of byte to copy
*/
static inline void * lv_memcpy_small(void * dst, const void * src, size_t len)
LV_ATTRIBUTE_FAST_MEM static inline void * lv_memcpy_small(void * dst, const void * src, size_t len)
{
uint8_t * d8 = (uint8_t *)dst;
const uint8_t * s8 = (const uint8_t *)src;
@@ -167,7 +167,7 @@ static inline void * lv_memcpy_small(void * dst, const void * src, size_t len)
* @param v value to set [0..255]
* @param len number of byte to set
*/
void lv_memset(void * dst, uint8_t v, size_t len);
LV_ATTRIBUTE_FAST_MEM void lv_memset(void * dst, uint8_t v, size_t len);
/**
* Same as `memset(dst, 0x00, len)` but optimized for 4 byte operation.
@@ -175,7 +175,7 @@ void lv_memset(void * dst, uint8_t v, size_t len);
* @param dst pointer to the destination buffer
* @param len number of byte to set
*/
void lv_memset_00(void * dst, size_t len);
LV_ATTRIBUTE_FAST_MEM void lv_memset_00(void * dst, size_t len);
/**
* Same as `memset(dst, 0xFF, len)` but optimized for 4 byte operation.
@@ -183,7 +183,7 @@ void lv_memset_00(void * dst, size_t len);
* @param dst pointer to the destination buffer
* @param len number of byte to set
*/
void lv_memset_ff(void * dst, size_t len);
LV_ATTRIBUTE_FAST_MEM void lv_memset_ff(void * dst, size_t len);
/**********************
* MACROS