feat(gpu): Update lv_gpu_arm2d with new features (#3340)

* feat(gpu): Update lv_gpu_arm2d with new features

- Provide acceleration for
    * Transform
    * Recolour
    * Chrome-Key

* remove typos

* fix code-format issue

* update according to #3337

* remove the last /* *INDENT-ON* */
This commit is contained in:
Gabriel Wang
2022-05-16 04:15:49 +01:00
committed by GitHub
parent 2148ed99b0
commit 6ae0784251

View File

@@ -31,6 +31,7 @@
#pragma clang diagnostic ignored "-Wdisabled-macro-expansion" #pragma clang diagnostic ignored "-Wdisabled-macro-expansion"
#pragma clang diagnostic ignored "-Wunused-variable" #pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-but-set-variable" #pragma clang diagnostic ignored "-Wunused-but-set-variable"
#pragma clang diagnostic ignored "-Wint-conversion"
#endif #endif
@@ -53,6 +54,12 @@
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/
#if ( !defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
|| !__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& LV_COLOR_DEPTH == 32 \
&& !defined(__ARM_2D_LVGL_CFG_NO_WARNING__)
#warning Please set macro __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__ to 1 to get more acceleration opportunities. Or you can define macro __ARM_2D_LVGL_CFG_NO_WARNING__ to suppress this warning.
#endif
#define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing()) #define MAX_BUF_SIZE (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing())
@@ -82,6 +89,13 @@
#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb16_cl_key_copy #define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb16_cl_key_copy
#define __arm_2d_impl_alpha_blending_colour_keying \ #define __arm_2d_impl_alpha_blending_colour_keying \
__arm_2d_impl_rgb565_alpha_blending_colour_keying __arm_2d_impl_rgb565_alpha_blending_colour_keying
#define arm_2d_tile_transform_with_src_mask_and_opacity \
arm_2d_rgb565_tile_transform_with_src_mask_and_opacity
#define arm_2d_tile_transform_with_opacity \
arm_2d_rgb565_tile_transform_with_opacity
#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_RGB565
#define color_int uint16_t #define color_int uint16_t
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
@@ -110,6 +124,12 @@
#define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb32_cl_key_copy #define __arm_2d_impl_cl_key_copy __arm_2d_impl_rgb32_cl_key_copy
#define __arm_2d_impl_alpha_blending_colour_keying \ #define __arm_2d_impl_alpha_blending_colour_keying \
__arm_2d_impl_cccn888_alpha_blending_colour_keying __arm_2d_impl_cccn888_alpha_blending_colour_keying
#define arm_2d_tile_transform_with_src_mask_and_opacity \
arm_2d_cccn888_tile_transform_with_src_mask_and_opacity
#define arm_2d_tile_transform_with_opacity \
arm_2d_cccn888_tile_transform_with_opacity
#define __ARM_2D_PIXEL_BLENDING_OPA __ARM_2D_PIXEL_BLENDING_OPA_CCCN888
#define color_int uint32_t #define color_int uint32_t
@@ -117,32 +137,172 @@
#error The specified LV_COLOR_DEPTH is not supported by this version of lv_gpu_arm2d.c. #error The specified LV_COLOR_DEPTH is not supported by this version of lv_gpu_arm2d.c.
#endif #endif
/* *INDENT-OFF* */ /* *INDENT-OFF* */
#define __ACCELERATE_PREPARE__() \ #define __PREPARE_LL_ACCELERATION__() \
int32_t src_stride = lv_area_get_width(coords); \ int32_t src_stride = lv_area_get_width(coords); \
\
uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA \ uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA \
? LV_IMG_PX_SIZE_ALPHA_BYTE \ ? LV_IMG_PX_SIZE_ALPHA_BYTE \
: sizeof(lv_color_t); \ : sizeof(lv_color_t); \
\
const uint8_t * src_buf_tmp = src_buf; \ const uint8_t * src_buf_tmp = src_buf; \
src_buf_tmp += src_stride \ src_buf_tmp += src_stride \
* (draw_area.y1 - coords->y1) \ * (draw_area.y1 - coords->y1) \
* px_size_byte; \ * px_size_byte; \
src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; \ src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte; \
\
lv_area_t blend_area2; \ lv_area_t blend_area2; \
if(!_lv_area_intersect(&blend_area2, \ if(!_lv_area_intersect(&blend_area2, \
&draw_area, \ &draw_area, \
draw_ctx->clip_area)) return; \ draw_ctx->clip_area)) return; \
\
int32_t w = lv_area_get_width(&blend_area2); \ int32_t w = lv_area_get_width(&blend_area2); \
int32_t h = lv_area_get_height(&blend_area2); \ int32_t h = lv_area_get_height(&blend_area2); \
\
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); \ lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area); \
\
lv_color_t * dest_buf = draw_ctx->buf; \ lv_color_t * dest_buf = draw_ctx->buf; \
dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1) \ dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1) \
+ (blend_area2.x1 - draw_ctx->buf_area->x1); \ + (blend_area2.x1 - draw_ctx->buf_area->x1); \
\
arm_2d_size_t copy_size = { \ arm_2d_size_t copy_size = { \
.iWidth = lv_area_get_width(&blend_area2), \ .iWidth = lv_area_get_width(&blend_area2), \
.iHeight = lv_area_get_height(&blend_area2), \ .iHeight = lv_area_get_height(&blend_area2), \
} }
#define __PREPARE_TARGET_TILE__(__blend_area) \
static arm_2d_tile_t target_tile; \
static arm_2d_region_t target_region; \
\
lv_color_t * dest_buf = draw_ctx->buf; \
\
target_tile = (arm_2d_tile_t) { \
.tRegion = { \
.tSize = { \
.iWidth = lv_area_get_width(draw_ctx->buf_area), \
.iHeight = lv_area_get_height(draw_ctx->buf_area), \
}, \
}, \
.tInfo.bIsRoot = true, \
.phwBuffer = (uint16_t *)draw_ctx->buf, \
}; \
\
target_region = (arm_2d_region_t) { \
.tLocation = { \
.iX = (__blend_area).x1 - draw_ctx->buf_area->x1, \
.iY = (__blend_area).y1 - draw_ctx->buf_area->y1, \
}, \
.tSize = { \
.iWidth = lv_area_get_width(&(__blend_area)), \
.iHeight = lv_area_get_height(&(__blend_area)), \
}, \
}
#define __PREPARE_SOURCE_TILE__(__dsc, __blend_area) \
static arm_2d_tile_t source_tile_orig; \
static arm_2d_tile_t source_tile; \
const lv_color_t * src_buf = (__dsc)->src_buf; \
if (src_buf) { \
source_tile_orig = (arm_2d_tile_t) { \
.tRegion = { \
.tSize = { \
.iWidth = lv_area_get_width((__dsc)->blend_area), \
.iHeight = lv_area_get_height((__dsc)->blend_area), \
}, \
}, \
.tInfo.bIsRoot = true, \
.phwBuffer = (uint16_t *)src_buf, \
}; \
\
arm_2d_tile_generate_child( \
&source_tile_orig, \
(arm_2d_region_t []) { \
{ \
.tLocation = { \
.iX = (__blend_area).x1 - (__dsc)->blend_area->x1, \
.iY = (__blend_area).y1 - (__dsc)->blend_area->y1, \
}, \
.tSize = source_tile_orig.tRegion.tSize, \
} \
}, \
&source_tile, \
false); \
source_tile.tInfo.bDerivedResource = true; \
}
#define __PREPARE_MASK_TILE__(__dsc, __blend_area, __mask, __is_chn) \
static arm_2d_tile_t mask_tile_orig; \
static arm_2d_tile_t mask_tile; \
if(NULL != (__mask)) { \
mask_tile_orig = (arm_2d_tile_t) { \
.tRegion = { \
.tSize = { \
.iWidth = lv_area_get_width((__dsc)->mask_area), \
.iHeight = lv_area_get_height((__dsc)->mask_area), \
}, \
}, \
.tInfo = { \
.bIsRoot = true, \
.bHasEnforcedColour = true, \
.tColourInfo = { \
.chScheme = (__is_chn) ? ARM_2D_CHANNEL_8in32 \
: ARM_2D_COLOUR_8BIT, \
}, \
}, \
.pchBuffer = ((uint8_t *)(__mask)) + (__is_chn) ? 3 : 0, \
}; \
\
arm_2d_tile_generate_child( \
&mask_tile_orig, \
(arm_2d_region_t []) { \
{ \
.tLocation = { \
.iX = (__dsc)->mask_area->x1 - (__blend_area).x1, \
.iY = (__dsc)->mask_area->y1 - (__blend_area).y1, \
}, \
.tSize = mask_tile_orig.tRegion.tSize, \
} \
}, \
&mask_tile, \
false); \
mask_tile.tInfo.bDerivedResource = true; \
}
/* *INDENT-ON* */
/* *INDENT-OFF* */
#define __RECOLOUR_WRAPPER(...) \
do { \
lv_color_t *rgb_tmp_buf = NULL; \
if(draw_dsc->recolor_opa > LV_OPA_MIN) { \
rgb_tmp_buf \
= lv_mem_buf_get(src_w * src_h * sizeof(lv_color_t)); \
if (NULL == rgb_tmp_buf) { \
LV_LOG_WARN( \
"Failed to allocate memory for accelerating recolour, " \
"use normal route instead."); \
break; \
} \
lv_memcpy(rgb_tmp_buf, src_buf, src_w * src_h * sizeof(lv_color_t));\
arm_2d_size_t copy_size = { \
.iWidth = src_w, \
.iHeight = src_h, \
}; \
/* apply re-colour */ \
__arm_2d_impl_colour_filling_with_opacity( \
(color_int *)rgb_tmp_buf, \
src_w, \
&copy_size, \
(color_int)draw_dsc->recolor.full, \
draw_dsc->recolor_opa); \
\
/* replace src_buf for the following operation */ \
src_buf = (const uint8_t *)rgb_tmp_buf; \
} \
__VA_ARGS__ \
if (NULL != rgb_tmp_buf) { \
lv_mem_buf_release(rgb_tmp_buf); \
} \
} while(0);
/* *INDENT-ON* */ /* *INDENT-ON* */
/********************** /**********************
@@ -153,8 +313,6 @@
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
#if __ARM_2D_HAS_HW_ACC__ #if __ARM_2D_HAS_HW_ACC__
LV_ATTRIBUTE_FAST_MEM LV_ATTRIBUTE_FAST_MEM
static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile, static bool lv_draw_arm2d_fill_colour(const arm_2d_tile_t * target_tile,
@@ -212,8 +370,6 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
const uint8_t * src_buf, const uint8_t * src_buf,
lv_img_cf_t cf); lv_img_cf_t cf);
/********************** /**********************
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
@@ -267,106 +423,16 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
return; return;
} }
static arm_2d_tile_t target_tile;
static arm_2d_tile_t source_tile_orig;
static arm_2d_tile_t source_tile;
static arm_2d_tile_t mask_tile_orig;
static arm_2d_tile_t mask_tile;
static arm_2d_region_t target_region;
bool is_accelerated = false; bool is_accelerated = false;
if(dsc->blend_mode == LV_BLEND_MODE_NORMAL if(dsc->blend_mode == LV_BLEND_MODE_NORMAL
&& lv_area_get_size(&blend_area) > 100) { && lv_area_get_size(&blend_area) > 100) {
lv_color_t * dest_buf = draw_ctx->buf; __PREPARE_TARGET_TILE__(blend_area);
__PREPARE_SOURCE_TILE__(dsc, blend_area);
__PREPARE_MASK_TILE__(dsc, blend_area, mask, false);
target_tile = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->buf_area),
.iHeight = lv_area_get_height(draw_ctx->buf_area),
},
},
.tInfo.bIsRoot = true,
.phwBuffer = (uint16_t *)draw_ctx->buf,
};
target_region = (arm_2d_region_t) {
.tLocation = {
.iX = blend_area.x1 - draw_ctx->buf_area->x1,
.iY = blend_area.y1 - draw_ctx->buf_area->y1,
},
.tSize = {
.iWidth = lv_area_get_width(&blend_area),
.iHeight = lv_area_get_height(&blend_area),
},
};
if(NULL != mask) {
mask_tile_orig = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(dsc->mask_area),
.iHeight = lv_area_get_height(dsc->mask_area),
},
},
.tInfo = {
.bIsRoot = true,
.bHasEnforcedColour = true,
.tColourInfo = {
.chScheme = ARM_2D_COLOUR_8BIT,
},
},
.pchBuffer = (uint8_t *)mask,
};
arm_2d_tile_generate_child(
&mask_tile_orig,
(arm_2d_region_t []) {
{
.tLocation = {
.iX = dsc->mask_area->x1 - blend_area.x1,
.iY = dsc->mask_area->y1 - blend_area.y1,
},
.tSize = mask_tile_orig.tRegion.tSize,
}
},
&mask_tile,
false);
mask_tile.tInfo.bDerivedResource = true;
}
const lv_color_t * src_buf = dsc->src_buf;
if(src_buf) { if(src_buf) {
source_tile_orig = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(dsc->blend_area),
.iHeight = lv_area_get_height(dsc->blend_area),
},
},
.tInfo.bIsRoot = true,
.phwBuffer = (uint16_t *)src_buf,
};
arm_2d_tile_generate_child(
&source_tile_orig,
(arm_2d_region_t []) {
{
.tLocation = {
.iX = blend_area.x1 - dsc->blend_area->x1,
.iY = blend_area.y1 - dsc->blend_area->y1,
},
.tSize = source_tile_orig.tRegion.tSize,
}
},
&source_tile,
false);
source_tile.tInfo.bDerivedResource = true;
is_accelerated = lv_draw_arm2d_tile_copy( is_accelerated = lv_draw_arm2d_tile_copy(
&target_tile, &target_tile,
&target_region, &target_region,
@@ -560,7 +626,7 @@ static void lv_draw_arm2d_blend(lv_draw_ctx_t * draw_ctx, const lv_draw_sw_blend
lv_coord_t mask_stride; lv_coord_t mask_stride;
if(mask) { if(mask) {
mask_stride = lv_area_get_width(dsc->mask_area); mask_stride = lv_area_get_width(dsc->mask_area);
mask += mask_stride * (dsc->mask_area->y1 - blend_area.y1) + (dsc->mask_area->x1 - blend_area.x1); mask += mask_stride * (blend_area.y1 - dsc->mask_area->y1) + (blend_area.x1 - dsc->mask_area->x1);
} }
else { else {
mask_stride = 0; mask_stride = 0;
@@ -763,7 +829,6 @@ static bool arm_2d_copy_normal(lv_color_t * dest_buf,
return true; return true;
} }
LV_ATTRIBUTE_FAST_MEM LV_ATTRIBUTE_FAST_MEM
static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx, static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
const lv_draw_img_dsc_t * draw_dsc, const lv_draw_img_dsc_t * draw_dsc,
@@ -793,6 +858,16 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
blend_dsc.blend_area = coords; blend_dsc.blend_area = coords;
lv_draw_sw_blend(draw_ctx, &blend_dsc); lv_draw_sw_blend(draw_ctx, &blend_dsc);
} }
else if(!mask_any && !transform && cf == LV_IMG_CF_ALPHA_8BIT) {
blend_dsc.mask_buf = (lv_opa_t *)src_buf;
blend_dsc.mask_area = coords;
blend_dsc.src_buf = NULL;
blend_dsc.color = draw_dsc->recolor;
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
blend_dsc.blend_area = coords;
lv_draw_sw_blend(draw_ctx, &blend_dsc);
}
/*In the other cases every pixel need to be checked one-by-one*/ /*In the other cases every pixel need to be checked one-by-one*/
else { else {
blend_area.x1 = draw_ctx->clip_area->x1; blend_area.x1 = draw_ctx->clip_area->x1;
@@ -834,12 +909,27 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
blend_dsc.mask_res = mask_res_def; blend_dsc.mask_res = mask_res_def;
if((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) && (!transform)) { bool is_accelerated = false;
if(!transform) {
if(LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) {
/* copy with colour keying */ /* copy with colour keying */
__ACCELERATE_PREPARE__(); /* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
lv_color_t chrome_key = LV_COLOR_CHROMA_KEY;
/* calculate new chrome-key colour */
if(draw_dsc->recolor_opa > LV_OPA_MIN) {
__ARM_2D_PIXEL_BLENDING_OPA(
(color_int *) & (draw_dsc->recolor.full),
(color_int *) & (chrome_key.full),
draw_dsc->recolor_opa
);
}
__PREPARE_LL_ACCELERATION__();
//lv_area_move(&blend_area2, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
if(blend_dsc.opa >= LV_OPA_MAX) { if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_cl_key_copy( __arm_2d_impl_cl_key_copy(
(color_int *)src_buf_tmp, (color_int *)src_buf_tmp,
@@ -847,7 +937,7 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
(color_int *)dest_buf, (color_int *)dest_buf,
dest_stride, dest_stride,
&copy_size, &copy_size,
(color_int)LV_COLOR_CHROMA_KEY.full); (color_int)chrome_key.full);
} }
else { else {
__arm_2d_impl_alpha_blending_colour_keying( __arm_2d_impl_alpha_blending_colour_keying(
@@ -857,30 +947,227 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
dest_stride, dest_stride,
&copy_size, &copy_size,
blend_dsc.opa, blend_dsc.opa,
(color_int)LV_COLOR_CHROMA_KEY.full); (color_int)chrome_key.full);
} }
is_accelerated = true;
)
/* *INDENT-ON* */
} }
else if((LV_COLOR_DEPTH == 32) else if((LV_COLOR_DEPTH == 32)
&& !mask_any && !mask_any
&& !transform && (cf == LV_IMG_CF_TRUE_COLOR_ALPHA)) {
&& (draw_dsc->recolor_opa == LV_OPA_TRANSP)
&& (cf == LV_IMG_CF_TRUE_COLOR_ALPHA)
&& (blend_dsc.opa >= LV_OPA_MAX)) {
/* accelerate copy-with-source-masks-and-opacity */ /* accelerate copy-with-source-masks-and-opacity */
__ACCELERATE_PREPARE__(); /* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
uint8_t * mask_temp_buf = NULL;
if(blend_dsc.opa < LV_OPA_MAX) {
mask_temp_buf = lv_mem_buf_get(copy_size.iHeight * copy_size.iWidth);
if(NULL == mask_temp_buf) {
LV_LOG_WARN(
"Failed to allocate memory for alpha mask,"
" use normal route instead.");
break;
}
lv_memset_00(mask_temp_buf, copy_size.iHeight * copy_size.iWidth);
__arm_2d_impl_gray8_colour_filling_channel_mask_opacity(
mask_temp_buf,
src_stride,
(uint32_t *)
((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
src_stride,
&copy_size,
0xFF,
blend_dsc.opa);
__arm_2d_impl_src_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
mask_temp_buf,
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
lv_mem_buf_release(mask_temp_buf);
}
else {
__arm_2d_impl_src_chn_msk_copy( __arm_2d_impl_src_chn_msk_copy(
(color_int *)src_buf_tmp, (color_int *)src_buf_tmp,
src_stride, src_stride,
(uint32_t *)((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1), (uint32_t *)
((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
src_stride, src_stride,
&copy_size, &copy_size,
(color_int *)dest_buf, (color_int *)dest_buf,
dest_stride, dest_stride,
&copy_size); &copy_size);
} }
else while(blend_area.y1 <= y_last) {
is_accelerated = true;
)
/* *INDENT-ON* */
}
else if(!mask_any && (cf == LV_IMG_CF_TRUE_COLOR)) {
/* accelerate copy-with-source-masks-and-opacity */
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
__PREPARE_LL_ACCELERATION__();
if(blend_dsc.opa >= LV_OPA_MAX) {
__arm_2d_impl_copy(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
else {
__arm_2d_impl_alpha_blending(
(color_int *)src_buf_tmp,
src_stride,
(color_int *)dest_buf,
dest_stride,
&copy_size,
blend_dsc.opa);
}
is_accelerated = true;
)
/* *INDENT-ON* */
}
}
else if(!mask_any
#if defined(__ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__) && __ARM_2D_HAS_ANTI_ALIAS_TRANSFORM__
&& (draw_dsc->antialias == 1)
#else
&& (draw_dsc->antialias == 0)
#endif
&& (draw_dsc->recolor_opa == LV_OPA_TRANSP)
&& (((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf)
|| (LV_IMG_CF_TRUE_COLOR == cf))
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) && __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
|| ((LV_IMG_CF_TRUE_COLOR_ALPHA == cf)
&& (LV_COLOR_DEPTH == 32))
#endif
)
) {
/* *INDENT-OFF* */
__RECOLOUR_WRAPPER(
/* accelerate transform without re-color */
static arm_2d_tile_t target_tile_origin;
static arm_2d_tile_t target_tile;
arm_2d_region_t clip_region;
static arm_2d_region_t target_region;
lv_color_t * dest_buf = draw_ctx->buf;
target_tile_origin = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->buf_area),
.iHeight = lv_area_get_height(draw_ctx->buf_area),
},
},
.tInfo.bIsRoot = true,
.phwBuffer = (uint16_t *)draw_ctx->buf,
};
clip_region = (arm_2d_region_t) {
.tLocation = {
.iX = draw_ctx->clip_area->x1 - draw_ctx->buf_area->x1,
.iY = draw_ctx->clip_area->y1 - draw_ctx->buf_area->y1,
},
.tSize = {
.iWidth = lv_area_get_width(draw_ctx->clip_area),
.iHeight = lv_area_get_height(draw_ctx->clip_area),
},
};
arm_2d_tile_generate_child(&target_tile_origin,
&clip_region,
&target_tile,
false);
target_region = (arm_2d_region_t) {
.tLocation = {
.iX = coords->x1 - draw_ctx->clip_area->x1,
.iY = coords->y1 - draw_ctx->clip_area->y1,
},
.tSize = {
.iWidth = lv_area_get_width(coords),
.iHeight = lv_area_get_height(coords),
},
};
static arm_2d_tile_t source_tile;
source_tile = (arm_2d_tile_t) {
.tRegion = {
.tSize = {
.iWidth = src_w,
.iHeight = src_h,
},
},
.tInfo.bIsRoot = true,
.pchBuffer = (uint8_t *)src_buf,
};
static arm_2d_tile_t mask_tile;
mask_tile = source_tile;
mask_tile.tInfo.bHasEnforcedColour = true;
mask_tile.tInfo.tColourInfo.chScheme = ARM_2D_CHANNEL_8in32;
mask_tile.pchBuffer += 3;
static arm_2d_location_t source_center, target_center;
source_center.iX = draw_dsc->pivot.x;
source_center.iY = draw_dsc->pivot.y;
if((LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED == cf) ||
(LV_IMG_CF_TRUE_COLOR == cf)) {
arm_2d_tile_transform_with_opacity(
&source_tile,
&target_tile,
&target_region,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
(color_int)LV_COLOR_CHROMA_KEY.full,
blend_dsc.opa);
is_accelerated = true;
}
#if defined(__ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__) \
&& __ARM_2D_CFG_SUPPORT_COLOUR_CHANNEL_ACCESS__
else if((LV_IMG_CF_TRUE_COLOR_ALPHA == cf) &&
(LV_COLOR_DEPTH == 32)) {
arm_2d_tile_transform_with_src_mask_and_opacity(
&source_tile,
&mask_tile,
&target_tile,
&target_region,
source_center,
ARM_2D_ANGLE((draw_dsc->angle / 10.0f)),
draw_dsc->zoom / 256.0f,
blend_dsc.opa);
is_accelerated = true;
}
#endif
)
/* *INDENT-ON* */
}
/* *INDENT-OFF* */
if(!is_accelerated) while(blend_area.y1 <= y_last) {
/*Apply transformations if any or separate the channels*/ /*Apply transformations if any or separate the channels*/
lv_area_t transform_area; lv_area_t transform_area;
lv_area_copy(&transform_area, &blend_area); lv_area_copy(&transform_area, &blend_area);
@@ -895,15 +1182,18 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
/*Apply recolor*/ /*Apply recolor*/
if(draw_dsc->recolor_opa > LV_OPA_MIN) { if(draw_dsc->recolor_opa > LV_OPA_MIN) {
uint16_t premult_v[3]; arm_2d_size_t copy_size = {
lv_opa_t recolor_opa = draw_dsc->recolor_opa; .iWidth = buf_w,
lv_color_t recolor = draw_dsc->recolor; .iHeight = buf_h,
lv_color_premult(recolor, recolor_opa, premult_v); };
recolor_opa = 255 - recolor_opa;
uint32_t i; /* apply re-colour */
for(i = 0; i < buf_size; i++) { __arm_2d_impl_colour_filling_with_opacity(
rgb_buf[i] = lv_color_mix_premult(premult_v, rgb_buf[i], recolor_opa); (color_int *)rgb_buf,
} buf_w,
&copy_size,
(color_int)draw_dsc->recolor.full,
draw_dsc->recolor_opa);
} }
#if LV_DRAW_COMPLEX #if LV_DRAW_COMPLEX
/*Apply the masks if any*/ /*Apply the masks if any*/
@@ -940,286 +1230,11 @@ static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
} }
} }
#if 0 /* the old version, left here for reference only */
LV_ATTRIBUTE_FAST_MEM
static void lv_draw_arm2d_img_decoded(struct _lv_draw_ctx_t * draw_ctx,
const lv_draw_img_dsc_t * draw_dsc,
const lv_area_t * coords,
const uint8_t * src_buf,
lv_img_cf_t cf)
{
bool mask_any = lv_draw_mask_is_any(draw_ctx->clip_area);
/*The simplest case just copy the pixels into the draw_buf*/
if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE &&
cf == LV_IMG_CF_TRUE_COLOR && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
return ;
}
/*In the other cases every pixel need to be checked one-by-one*/
else {
/*Use the clip area as draw area*/
lv_area_t draw_area;
lv_area_copy(&draw_area, draw_ctx->clip_area);
lv_draw_sw_blend_dsc_t blend_dsc;
lv_memset_00(&blend_dsc, sizeof(blend_dsc));
blend_dsc.opa = draw_dsc->opa;
blend_dsc.blend_mode = draw_dsc->blend_mode;
//#if LV_DRAW_COMPLEX
/*The pixel size in byte is different if an alpha byte is added too*/
uint8_t px_size_byte = cf == LV_IMG_CF_TRUE_COLOR_ALPHA ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t);
/*Go to the first displayed pixel of the map*/
int32_t src_stride = lv_area_get_width(coords);
lv_color_t c;
lv_color_t chroma_keyed_color = LV_COLOR_CHROMA_KEY;
uint32_t px_i = 0;
const uint8_t * map_px;
lv_coord_t draw_area_h = lv_area_get_height(&draw_area);
lv_coord_t draw_area_w = lv_area_get_width(&draw_area);
lv_area_t blend_area;
blend_area.x1 = draw_area.x1;
blend_area.x2 = draw_area.x2;
blend_area.y1 = draw_area.y1;
blend_area.y2 = blend_area.y1;
blend_dsc.blend_area = &blend_area;
bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false;
/*Simple ARGB image. Handle it as special case because it's very common*/
if(!mask_any && !transform && cf == LV_IMG_CF_TRUE_COLOR_ALPHA && draw_dsc->recolor_opa == LV_OPA_TRANSP) {
const uint8_t * src_buf_tmp = src_buf;
src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
#if LV_COLOR_DEPTH == 32
if(blend_dsc.opa >= LV_OPA_MAX) {
lv_area_t blend_area2;
if(!_lv_area_intersect(&blend_area2, &draw_area, draw_ctx->clip_area)) return;
int32_t w = lv_area_get_width(&blend_area2);
int32_t h = lv_area_get_height(&blend_area2);
lv_coord_t dest_stride = lv_area_get_width(draw_ctx->buf_area);
lv_color_t * dest_buf = draw_ctx->buf;
dest_buf += dest_stride * (blend_area2.y1 - draw_ctx->buf_area->y1)
+ (blend_area2.x1 - draw_ctx->buf_area->x1);
arm_2d_size_t copy_size = {
.iWidth = lv_area_get_width(&blend_area2),
.iHeight = lv_area_get_height(&blend_area2),
};
//lv_area_move(&blend_area2, -draw_ctx->buf_area->x1, -draw_ctx->buf_area->y1);
__arm_2d_impl_src_chn_msk_copy(
(color_int *)src_buf_tmp,
src_stride,
(uint32_t *)((uintptr_t)src_buf_tmp + LV_IMG_PX_SIZE_ALPHA_BYTE - 1),
src_stride,
&copy_size,
(color_int *)dest_buf,
dest_stride,
&copy_size);
}
else
#endif
{
lv_draw_sw_img_decoded(draw_ctx, draw_dsc, coords, src_buf, cf);
return ;
}
}
/*Most complicated case: transform or other mask or chroma keyed*/
else {
/*Build the image and a mask line-by-line*/
uint32_t hor_res = (uint32_t) lv_disp_get_hor_res(_lv_refr_get_disp_refreshing());
uint32_t mask_buf_size = lv_area_get_size(&draw_area) > hor_res ? hor_res : lv_area_get_size(&draw_area);
lv_color_t * src_buf_rgb = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t));
lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size);
blend_dsc.mask_buf = mask_buf;
blend_dsc.mask_area = &blend_area;
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
blend_dsc.src_buf = src_buf_rgb;
const uint8_t * src_buf_tmp = NULL;
#if LV_DRAW_COMPLEX
lv_img_transform_dsc_t trans_dsc;
lv_memset_00(&trans_dsc, sizeof(lv_img_transform_dsc_t));
if(transform) {
trans_dsc.cfg.angle = draw_dsc->angle;
trans_dsc.cfg.zoom = draw_dsc->zoom;
trans_dsc.cfg.src = src_buf;
trans_dsc.cfg.src_w = src_stride;
trans_dsc.cfg.src_h = lv_area_get_height(coords);
trans_dsc.cfg.cf = cf;
trans_dsc.cfg.pivot_x = draw_dsc->pivot.x;
trans_dsc.cfg.pivot_y = draw_dsc->pivot.y;
trans_dsc.cfg.color = draw_dsc->recolor;
trans_dsc.cfg.antialias = draw_dsc->antialias;
_lv_img_buf_transform_init(&trans_dsc);
}
else
#endif
{
src_buf_tmp = src_buf;
src_buf_tmp += src_stride * (draw_area.y1 - coords->y1) * px_size_byte;
src_buf_tmp += (draw_area.x1 - coords->x1) * px_size_byte;
}
uint16_t recolor_premult[3] = {0};
lv_opa_t recolor_opa_inv = 255 - draw_dsc->recolor_opa;
if(draw_dsc->recolor_opa != 0) {
lv_color_premult(draw_dsc->recolor, draw_dsc->recolor_opa, recolor_premult);
}
blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
/*Prepare the `mask_buf`if there are other masks*/
if(mask_any) {
lv_memset_ff(mask_buf, mask_buf_size);
}
int32_t x;
int32_t y;
#if LV_DRAW_COMPLEX
int32_t rot_y = blend_area.y1 - coords->y1;
#endif
for(y = 0; y < draw_area_h; y++) {
map_px = src_buf_tmp;
#if LV_DRAW_COMPLEX
uint32_t px_i_start = px_i;
int32_t rot_x = blend_area.x1 - coords->x1;
#endif
for(x = 0; x < draw_area_w; x++, px_i++, map_px += px_size_byte) {
#if LV_DRAW_COMPLEX
if(transform) {
/*Transform*/
bool ret;
ret = _lv_img_buf_transform(&trans_dsc, rot_x + x, rot_y + y);
if(ret == false) {
mask_buf[px_i] = LV_OPA_TRANSP;
continue;
}
else {
mask_buf[px_i] = trans_dsc.res.opa;
c.full = trans_dsc.res.color.full;
}
}
/*No transform*/
else
#endif
{
if(cf == LV_IMG_CF_TRUE_COLOR_ALPHA) {
lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1];
mask_buf[px_i] = px_opa;
if(px_opa == 0) {
#if LV_COLOR_DEPTH == 32
src_buf_rgb[px_i].full = 0;
#endif
continue;
}
}
else {
mask_buf[px_i] = 0xFF;
}
#if LV_COLOR_DEPTH == 1
c.full = map_px[0];
#elif LV_COLOR_DEPTH == 8
c.full = map_px[0];
#elif LV_COLOR_DEPTH == 16
c.full = map_px[0] + (map_px[1] << 8);
#elif LV_COLOR_DEPTH == 32
c.full = *((uint32_t *)map_px);
c.ch.alpha = 0xFF;
#endif
if(cf == LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED) {
if(c.full == chroma_keyed_color.full) {
mask_buf[px_i] = LV_OPA_TRANSP;
#if LV_COLOR_DEPTH == 32
src_buf_rgb[px_i].full = 0;
#endif
continue;
}
}
}
if(draw_dsc->recolor_opa != 0) {
c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv);
}
src_buf_rgb[px_i].full = c.full;
}
#if LV_DRAW_COMPLEX
/*Apply the masks if any*/
if(mask_any) {
lv_draw_mask_res_t mask_res_sub;
mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, blend_area.x1,
y + draw_area.y1, draw_area_w);
if(mask_res_sub == LV_DRAW_MASK_RES_TRANSP) {
lv_memset_00(mask_buf + px_i_start, draw_area_w);
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
}
else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) {
blend_dsc.mask_res = LV_DRAW_MASK_RES_CHANGED;
}
}
#endif
src_buf_tmp += src_stride * px_size_byte;
if(px_i + draw_area_w < mask_buf_size) {
blend_area.y2 ++;
}
else {
lv_draw_sw_blend(draw_ctx, &blend_dsc);
blend_area.y1 = blend_area.y2 + 1;
blend_area.y2 = blend_area.y1;
px_i = 0;
blend_dsc.mask_res = (cf != LV_IMG_CF_TRUE_COLOR || draw_dsc->angle ||
draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
/*Prepare the `mask_buf`if there are other masks*/
if(mask_any) {
lv_memset_ff(mask_buf, mask_buf_size);
}
}
}
/*Flush the last part*/
if(blend_area.y1 != blend_area.y2) {
blend_area.y2--;
lv_draw_sw_blend(draw_ctx, &blend_dsc);
}
lv_mem_buf_release(mask_buf);
lv_mem_buf_release(src_buf_rgb);
}
}
}
#endif
static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx) static void lv_gpu_arm2d_wait_cb(lv_draw_ctx_t * draw_ctx)
{ {
lv_disp_t * disp = _lv_refr_get_disp_refreshing(); lv_disp_t * disp = _lv_refr_get_disp_refreshing();
arm_2d_op_wait_async(NULL);
if(disp->driver && disp->driver->wait_cb) { if(disp->driver && disp->driver->wait_cb) {
disp->driver->wait_cb(disp->driver); disp->driver->wait_cb(disp->driver);
} }