add builtin STM32 DMA2D support
This commit is contained in:
@@ -177,6 +177,8 @@ typedef void * lv_group_user_data_t;
|
||||
|
||||
/* 1: Enable GPU interface*/
|
||||
#define LV_USE_GPU 1
|
||||
#define LV_GPU_INCLUDE <stdint.h> /*E.g. "stm32f7xx_hal.h"*/
|
||||
#define LV_USE_GPU_STM32_DMA2D 1
|
||||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
#define LV_USE_FILESYSTEM 1
|
||||
|
||||
@@ -263,6 +263,12 @@
|
||||
#ifndef LV_USE_GPU
|
||||
#define LV_USE_GPU 1
|
||||
#endif
|
||||
#ifndef LV_GPU_INCLUDE
|
||||
#define LV_GPU_INCLUDE <stdint.h> /*E.g. "stm32f7xx_hal.h"*/
|
||||
#endif
|
||||
#ifndef LV_USE_GPU_STM32_DMA2D
|
||||
#define LV_USE_GPU_STM32_DMA2D 1
|
||||
#endif
|
||||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
#ifndef LV_USE_FILESYSTEM
|
||||
|
||||
@@ -11,14 +11,30 @@
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_hal/lv_hal_disp.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
#include LV_GPU_INCLUDE
|
||||
|
||||
static DMA2D_HandleTypeDef hdma2d;
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define FILL_DIRECT_LEN 32
|
||||
#define FILL_DIRECT_MASK 0x1F
|
||||
#define GPU_SIZE_LIMIT 240
|
||||
|
||||
#if LV_USE_GPU_STM32_CHROM_ART
|
||||
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP
|
||||
#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*/
|
||||
#undef LV_USE_GPU_STM32_DMA2D
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#undef LV_USE_GPU_STM32_CHROM_ART
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -65,8 +81,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 +99,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 +119,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`
|
||||
*/
|
||||
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,
|
||||
@@ -121,7 +137,7 @@ void lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area,
|
||||
{
|
||||
/*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);
|
||||
@@ -166,14 +182,26 @@ void lv_blend_fill(const lv_area_t * clip_area, const lv_area_t * fill_area,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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`
|
||||
*/
|
||||
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` */
|
||||
@@ -260,6 +288,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
|
||||
*/
|
||||
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)
|
||||
@@ -272,11 +313,11 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
/*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;
|
||||
@@ -284,33 +325,39 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
/*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_CHROM_ART
|
||||
if(lv_area_get_size(draw_area) >= 240) {
|
||||
#if __DCACHE_PRESENT
|
||||
SCB_CleanInvalidateDCache();
|
||||
#endif
|
||||
hdma2d.Instance = DMA2D;
|
||||
hdma2d.Init.Mode = DMA2D_R2M;
|
||||
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
|
||||
hdma2d.Init.OutputOffset = disp_w - draw_area_w;
|
||||
hdma2d.LayerCfg[1].InputAlpha = DMA2D_NO_MODIF_ALPHA;
|
||||
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
|
||||
hdma2d.LayerCfg[1].InputOffset = 0;
|
||||
|
||||
/*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;
|
||||
/* DMA2D Initialization */
|
||||
if (HAL_DMA2D_Init(&hdma2d) == HAL_OK) {
|
||||
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) == HAL_OK) {
|
||||
HAL_DMA2D_Start(&hdma2d, (uint32_t)lv_color_to32(color), (uint32_t)disp_buf_first, draw_area_w, draw_area_h);
|
||||
HAL_DMA2D_PollForTransfer(&hdma2d, HAL_MAX_DELAY);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
#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*/
|
||||
@@ -321,8 +368,8 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
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;
|
||||
}
|
||||
@@ -334,48 +381,81 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
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_CHROM_ART && 0
|
||||
if(lv_area_get_size(draw_area) > 240) {
|
||||
#if __DCACHE_PRESENT
|
||||
SCB_CleanInvalidateDCache();
|
||||
#endif
|
||||
/* 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 = disp_w - draw_area_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 = disp_w - draw_area_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) disp_buf_first, (uint32_t)disp_buf_first, draw_area_w, draw_area_h);
|
||||
HAL_DMA2D_PollForTransfer(&hdma2d, HAL_MAX_DELAY);
|
||||
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
|
||||
@@ -385,7 +465,7 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
#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
|
||||
@@ -397,10 +477,10 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
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;
|
||||
@@ -421,7 +501,7 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
}
|
||||
|
||||
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
|
||||
@@ -429,46 +509,60 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
|
||||
#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)
|
||||
@@ -595,7 +689,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
|
||||
*/
|
||||
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)
|
||||
@@ -604,18 +710,18 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
/*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;
|
||||
@@ -629,70 +735,126 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
|
||||
/*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_CHROM_ART
|
||||
if(lv_area_get_size(draw_area) >= 240) {
|
||||
#if __DCACHE_PRESENT
|
||||
SCB_CleanInvalidateDCache();
|
||||
#endif
|
||||
hdma2d.Instance = DMA2D;
|
||||
hdma2d.Init.Mode = DMA2D_M2M;
|
||||
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
|
||||
hdma2d.Init.OutputOffset = disp_w - draw_area_w;
|
||||
|
||||
/* Foreground layer */
|
||||
hdma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
|
||||
hdma2d.LayerCfg[1].InputAlpha = opa;
|
||||
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
|
||||
hdma2d.LayerCfg[1].InputOffset = map_w - draw_area_w;
|
||||
hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
|
||||
|
||||
/* DMA2D Initialization */
|
||||
if (HAL_DMA2D_Init(&hdma2d) == HAL_OK) {
|
||||
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
||||
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) == HAL_OK) {
|
||||
HAL_DMA2D_Start(&hdma2d, (uint32_t)map_buf_first, (uint32_t)disp_buf_first, draw_area_w, draw_area_h);
|
||||
HAL_DMA2D_PollForTransfer(&hdma2d, HAL_MAX_DELAY);
|
||||
}
|
||||
}
|
||||
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_CHROM_ART
|
||||
if(lv_area_get_size(draw_area) >= 256) {
|
||||
#if __DCACHE_PRESENT
|
||||
SCB_CleanInvalidateDCache();
|
||||
#endif
|
||||
hdma2d.Instance = DMA2D;
|
||||
hdma2d.Init.Mode = DMA2D_M2M_BLEND;
|
||||
hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT;
|
||||
hdma2d.Init.OutputOffset = disp_w - draw_area_w;
|
||||
|
||||
/* Background layer */
|
||||
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
|
||||
hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_FORMAT;
|
||||
hdma2d.LayerCfg[0].InputOffset = disp_w - draw_area_w;
|
||||
hdma2d.LayerCfg[0].AlphaInverted = DMA2D_REGULAR_ALPHA;
|
||||
|
||||
/* Foreground layer */
|
||||
hdma2d.LayerCfg[1].AlphaMode = DMA2D_REPLACE_ALPHA;
|
||||
hdma2d.LayerCfg[1].InputAlpha = opa;
|
||||
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT;
|
||||
hdma2d.LayerCfg[1].InputOffset = map_w - draw_area_w;
|
||||
hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA;
|
||||
|
||||
/* DMA2D Initialization */
|
||||
if (HAL_DMA2D_Init(&hdma2d) == HAL_OK) {
|
||||
HAL_DMA2D_ConfigLayer(&hdma2d, 0);
|
||||
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) == HAL_OK) {
|
||||
HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t)map_buf_first, (uint32_t)disp_buf_first, (uint32_t)disp_buf_first, draw_area_w, draw_area_h);
|
||||
HAL_DMA2D_PollForTransfer(&hdma2d, HAL_MAX_DELAY);
|
||||
}
|
||||
}
|
||||
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
|
||||
@@ -701,13 +863,13 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -728,7 +890,7 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
}
|
||||
|
||||
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
|
||||
@@ -736,33 +898,32 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -556,7 +556,7 @@ static void draw_letter_normal(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, 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));
|
||||
}
|
||||
}
|
||||
@@ -756,7 +756,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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ static void draw_line_hor(const lv_point_t * point1, const lv_point_t * point2,
|
||||
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 @@ static void draw_line_ver(const lv_point_t * point1, const lv_point_t * point2,
|
||||
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 @@ static void draw_line_skew(const lv_point_t * point1, const lv_point_t * point2,
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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++;
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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,8 +874,8 @@ 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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1060,7 +1060,7 @@ static void shadow_draw_corner_buf(const lv_area_t * coords, uint16_t * sh_buf,
|
||||
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 {
|
||||
|
||||
@@ -37,6 +37,38 @@
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
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);
|
||||
|
||||
@@ -597,6 +597,8 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
|
||||
(uint8_t)((c & 0xF) | ((c & 0xF) << 4)));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user