1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

blending a color mixing speed up

This commit is contained in:
Gabor Kiss-Vamosi 2020-03-19 15:29:03 +01:00
parent dd17e7c9b2
commit 3ee8763838
5 changed files with 99 additions and 75 deletions

View File

@ -268,18 +268,18 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
}
for(; x <= draw_area->x2; x += FILL_DIRECT_LEN) {
memcpy(&disp_buf_tmp[x], &disp_buf_tmp[draw_area->x1], FILL_DIRECT_LEN * sizeof(lv_color_t));
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++) {
memcpy(&disp_buf_tmp[draw_area->x1], &disp_buf_tmp_ori[draw_area->x1], draw_area_w * sizeof(lv_color_t));
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;
}
}
/*No mask with opacity*/
else {
#if LV_USE_GPU
if(disp->driver.gpu_blend_cb && draw_area_w > GPU_WIDTH_LIMIT) {
static lv_color_t blend_buf[LV_HOR_RES_MAX];
@ -294,6 +294,11 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
#endif
lv_color_t last_dest_color = LV_COLOR_BLACK;
lv_color_t last_res_color = lv_color_mix(color, last_dest_color, opa);
uint16_t color_premult[3];
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) {
@ -307,7 +312,7 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
else
#endif
{
last_res_color = lv_color_mix(color, disp_buf_tmp[x], opa);
last_res_color = lv_color_mix_premult(color_premult, disp_buf_tmp[x], opa_inv);
}
}
disp_buf_tmp[x] = last_res_color;
@ -333,26 +338,28 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
/*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(x = draw_area->x1; x <= draw_area->x2; x++) {
if(mask_tmp[x] == 0) continue;
if(mask_tmp[x] != last_mask || last_dest_color.full != disp_buf_tmp[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, mask_tmp[x], &last_res_color,
&last_res_color.ch.alpha);
}
else
#endif
{
if(mask_tmp[x] == LV_OPA_COVER) last_res_color = color;
else if(mask_tmp[x] == LV_OPA_TRANSP) last_res_color = disp_buf_tmp[x];
else if(disp_buf_tmp[x].full == color.full) last_res_color = color;
else last_res_color = lv_color_mix(color, disp_buf_tmp[x], mask_tmp[x]);
}
last_mask = mask_tmp[x];
last_dest_color.full = disp_buf_tmp[x].full;
if(*mask_tmp_x) {
if(*mask_tmp_x != last_mask || last_dest_color.full != disp_buf_tmp[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, *mask_tmp_x, &last_res_color,
&last_res_color.ch.alpha);
}
else
#endif
{
if(*mask_tmp_x == LV_OPA_COVER) last_res_color = color;
else if(disp_buf_tmp[x].full == color.full) last_res_color = color;
else last_res_color = lv_color_mix(color, disp_buf_tmp[x], *mask_tmp_x);
}
last_mask = *mask_tmp_x;
last_dest_color.full = disp_buf_tmp[x].full;
}
disp_buf_tmp[x] = last_res_color;
}
disp_buf_tmp[x] = last_res_color;
mask_tmp_x++;
}
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
@ -360,27 +367,30 @@ static void fill_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, con
}
/*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++) {
for(x = draw_area->x1; x <= draw_area->x2; x++) {
if(mask_tmp[x] == 0) continue;
if(mask_tmp[x] != last_mask || last_dest_color.full != disp_buf_tmp[x].full) {
lv_opa_t opa_tmp = mask_tmp[x] == LV_OPA_COVER ? opa : (uint32_t)((uint32_t)mask_tmp[x] * opa) >> 8;
const lv_opa_t * mask_tmp_x = &mask_tmp[draw_area->x1];
for(x = draw_area->x1; x <= draw_area->x2; 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 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,
&last_res_color.ch.alpha);
}
else
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,
&last_res_color.ch.alpha);
}
else
#endif
{
if(opa_tmp == LV_OPA_COVER) last_res_color = lv_color_mix(color, disp_buf_tmp[x], mask_tmp[x]);
else if(opa_tmp == LV_OPA_TRANSP) last_res_color = disp_buf_tmp[x];
else last_res_color = lv_color_mix(color, disp_buf_tmp[x], opa_tmp);
}
last_mask = mask_tmp[x];
last_dest_color.full = disp_buf_tmp[x].full;
}
disp_buf_tmp[x] = last_res_color;
{
if(opa_tmp == LV_OPA_COVER) last_res_color = color;
else last_res_color = lv_color_mix(color, disp_buf_tmp[x], opa_tmp);
}
last_mask = *mask_tmp_x;
last_dest_color.full = disp_buf_tmp[x].full;
}
disp_buf_tmp[x] = last_res_color;
}
mask_tmp_x++;
}
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
@ -567,7 +577,7 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
if(opa > LV_OPA_MAX) {
for(y = draw_area->y1; y <= draw_area->y2; y++) {
memcpy(&disp_buf_tmp[draw_area->x1], map_buf_tmp, draw_area_w * sizeof(lv_color_t));
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;
}
@ -612,20 +622,21 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
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_MIN) continue;
#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], mask_tmp[x], &res_color,
&opa_composed);
res_color.ch.alpha = opa_composed;
if(mask_tmp[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], mask_tmp[x], &res_color,
&opa_composed);
res_color.ch.alpha = opa_composed;
}
else
#endif
{
if(mask_tmp[x] > LV_OPA_MAX) res_color = map_buf_tmp[x];
else res_color = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
}
disp_buf_tmp[x] = res_color;
}
else
#endif
{
if(mask_tmp[x] > LV_OPA_MAX) res_color = map_buf_tmp[x];
else res_color = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
}
disp_buf_tmp[x] = res_color;//lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], mask_tmp[x]);
}
disp_buf_tmp += disp_w;
mask_tmp += draw_area_w;
@ -637,17 +648,18 @@ static void map_normal(const lv_area_t * disp_area, lv_color_t * disp_buf, cons
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] == 0) continue;
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[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);
}
else
#endif
{
disp_buf_tmp[x] = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
if(mask_tmp[x]) {
lv_opa_t opa_tmp = mask_tmp[x] >= LV_OPA_MAX ? opa : ((opa * mask_tmp[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);
}
else
#endif
{
disp_buf_tmp[x] = lv_color_mix(map_buf_tmp[x], disp_buf_tmp[x], opa_tmp);
}
}
}
disp_buf_tmp += disp_w;

View File

@ -417,6 +417,12 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
lv_img_buf_transform_init(&trans_dsc);
}
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);
}
lv_draw_mask_res_t mask_res;
mask_res = (alpha_byte || chroma_key || draw_dsc->angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER;
int32_t x;
@ -473,7 +479,7 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area,
}
if(draw_dsc->recolor_opa != 0) {
c = lv_color_mix(draw_dsc->recolor, c, draw_dsc->recolor_opa);
c = lv_color_mix_premult(recolor_premult, c, recolor_opa_inv);
}
map2[px_i].full = c.full;

View File

@ -19,6 +19,7 @@
*********************/
#define SHADOW_UPSACALE_SHIFT 6
#define SHADOW_ENHANCE 1
#define SPLIT_LIMIT 50
/**********************
* TYPEDEFS
@ -216,6 +217,9 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_re
}
}
bool split = false;
if(lv_area_get_width(&coords_bg) - 2 * rout > SPLIT_LIMIT) split = true;
lv_area_t fill_area;
fill_area.x1 = coords_bg.x1;
fill_area.x2 = coords_bg.x2;
@ -246,7 +250,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_re
/* If there is not other mask and drawing the corner area split the drawing to corner and middle areas
* because it the middle mask shuldn't be taken into account (therefore its faster)*/
if(simple_mode &&
if(simple_mode && split &&
(y < coords_bg.y1 + rout + 1 ||
y > coords_bg.y2 - rout - 1)) {
@ -277,7 +281,7 @@ static void draw_bg(const lv_area_t * coords, const lv_area_t * clip, lv_draw_re
lv_blend_fill(clip, &fill_area,
grad_color, mask_buf, mask_res, opa, dsc->bg_blend_mode);
}
else if(other_mask_cnt != 0) {
else if(other_mask_cnt != 0 || !split) {
lv_blend_fill(clip, &fill_area,
grad_color, mask_buf, mask_res, opa, dsc->bg_blend_mode);
}
@ -666,7 +670,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
int32_t y;
for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -684,7 +688,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
sh_buf_tmp = sh_buf ;
for(y = 0; y < corner_size - ver_mid_dist; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -725,7 +729,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
}
else {
for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -765,7 +769,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
sh_buf_tmp = sh_buf ;
for(y = 0; y < corner_size - ver_mid_dist + ver_mid_corr; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -783,7 +787,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
sh_buf_tmp = sh_buf ;
for(y = 0; y < corner_size - ver_mid_dist; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -821,7 +825,7 @@ static void draw_shadow(const lv_area_t * coords, const lv_area_t * clip, lv_dra
}
else {
for(y = corner_size; y < lv_area_get_height(&sh_area) - corner_size; y++) {
memcpy(mask_buf, sh_buf_tmp, corner_size);
lv_memcpy(mask_buf, sh_buf_tmp, corner_size);
mask_res = lv_draw_mask_apply(mask_buf + first_px, a.x1, a.y1, lv_area_get_width(&a));
if(mask_res == LV_DRAW_MASK_RES_FULL_COVER) mask_res = LV_DRAW_MASK_RES_CHANGED;
@ -1041,7 +1045,7 @@ static void shadow_blur_corner(lv_coord_t size, lv_coord_t sw, uint16_t * sh_ups
else left_val = sh_ups_tmp_buf[x - s_left - 1];
v += left_val;
}
memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t));
lv_memcpy(sh_ups_tmp_buf, sh_ups_blur_buf, size * sizeof(uint16_t));
sh_ups_tmp_buf += size;
}

View File

@ -17,6 +17,7 @@ extern "C" {
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include "lv_memcpy.h"
/*********************
* DEFINES

View File

@ -14,6 +14,7 @@ CSRCS += lv_utils.c
CSRCS += lv_async.c
CSRCS += lv_printf.c
CSRCS += lv_bidi.c
CSRCS += lv_memcpy.c
DEPPATH += --dep-path $(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc
VPATH += :$(LVGL_DIR)/$(LVGL_DIR_NAME)/src/lv_misc