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:
parent
dd17e7c9b2
commit
3ee8763838
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ extern "C" {
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "lv_memcpy.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user