zlgopen / awtk

AWTK = Toolkit AnyWhere(a cross-platform embedded GUI)
GNU Lesser General Public License v2.1
3.11k stars 768 forks source link

有几个透明bug #412

Open FandelXiong opened 4 years ago

FandelXiong commented 4 years ago

环境 linux framebuffer brga8888 后端agge

  1. window窗体支持全透明,但不支持半透明,发现是pixel.h的pixel_bgra8888_blend_rgba_dark和pixel_bgra8888_blend_rgba_premulti 对alpha没有做混合处理
  2. 如果现在显示一个背景全透明的window(window里有控件,能看到显示内容),打开一个dialog,当dialog关闭后,现象是dialog窗体只是往底层移动了,并没有关闭,全透明的window显示在最上层后,能透过背景看到dilaog
WNsACE commented 4 years ago

1,通过 pixel.h 看到,这两个函数应该是有和 alpha 通道做相乘的,而其中 pixel_bgra8888_blend_rgba_premulti 函数中的 rgba 参数中的 r,g,b 值是在传入函数前做了预乘 alpha 的操作。 ` static inline void pixel_bgra8888_blend_rgba_dark(void pixel, uint8_t a) { uint8_t p = (uint8_t*)pixel;

if (p[3] > 0xf4) { p[0] = (p[0] a) >> 8; p[1] = (p[1] a) >> 8; p[2] = (p[2] a) >> 8; p[3] = 0xff; } else { uint8_t s_a = 0xff - a; uint8_t out_a = tk_pixel_limit_uint8(p[3] + s_a - ((p[3] s_a) >> 8)); if (out_a > 0) { uint8_t d_a = (p[3] (0xff - a)) >> 8; p[0] = (p[0] d_a) / out_a; p[1] = (p[1] d_a) / out_a; p[2] = (p[2] d_a) / out_a; } p[3] = out_a; } }

static inline void pixel_bgra8888_blend_rgba_premulti(void pixel, rgba_t rgba) { uint8_t a = rgba.a; uint8_t p = (uint8_t*)pixel;

if (p[3] > 0xf4) { p[0] = ((p[0] a) >> 8) + rgba.b; p[1] = ((p[1] a) >> 8) + rgba.g; p[2] = ((p[2] a) >> 8) + rgba.r; p[3] = 0xff; } else { uint8_t s_a = 0xff - a; uint8_t out_a = tk_pixel_limit_uint8(p[3] + s_a - ((p[3] s_a) >> 8)); if (out_a > 0) { uint8_t d_a = (p[3] (0xff - rgba.a)) >> 8; p[0] = (p[0] d_a + (rgba.b << 8)) / out_a; p[1] = (p[1] d_a + (rgba.g << 8)) / out_a; p[2] = (p[2] d_a + (rgba.r << 8)) / out_a; } p[3] = out_a; } } ` 2,第二个问题应该是没有定义 WITH_LCD_CLEAR_ALPHA 宏,而你看到的底层的 dialog 窗体只是残影来的,而不是真实存在的,如果需要让窗体半透明或者全透明的话,需要开启 WITH_LCD_CLEAR_ALPHA 宏

FandelXiong commented 4 years ago

嗯,第一个问题确实修复了,我当时看的时候,没有做混合; 第二个我尝试开启后,残影问题解决了,但背景半透明情况下,性能会大幅度降低,1080p分辨率,需要绘制很长时间;

WNsACE commented 4 years ago

主要是两个问题导致速度变慢: 1,半透明的效果主要是每个像素点都进行混合运行(没有提供硬件加速的前提, WITH_G2D 宏就是开启硬件加速),而且当背景色为半透明的时候,混合运算的公式更加复杂了,所以增加每个像素点融合的运算量,我们可以看到 pixel_bgra8888_blend_rgba_premulti 函数中的 p[3] <= 0xf4 的时候就是背景色为半透明,可以看到算法变复杂了。 2,而且开了窗口半透效果后,每一帧都会在脏矩形区域上面刷新一层透明色来解决残影的问题,这样也会消耗性能,如果不开启脏矩形机制,就会整屏幕刷透明色,这样性能会比较低一点。

FandelXiong commented 4 years ago

感觉脏矩形机制有些问题,我现在背景是半透明,上面有些一些按钮,现在点击按钮,会触发整个界面重绘制,导致性能很低,按照我的理解,应该只重绘变化的这个区域把

WNsACE commented 4 years ago

因为不会吧,你把你的 xml 或者代码发出来看看?又或者你检查一下啊,你的使用三缓冲机制还是用双缓冲机制的,一般三缓冲机制都是不启用脏矩形机制的。

FandelXiong commented 4 years ago

`

WNsACE commented 4 years ago

canvas_fill_rect 函数只是给指定的区域填充颜色,但是在实际画到 buffer 上面的时候受到脏矩形的裁剪,所以你最好在 lcd_mem.inc 文件中的 lcd_mem_end_frame 函数中打印 lcd->dirty_rect 出来看看,你说的点击按钮会导致全屏刷新具体是指点击那个按钮?

FandelXiong commented 4 years ago

我刚才在lcd_mem_end_frame上打了断点,胀矩形还是1080p,按钮就是数字键盘上的任意一个

WNsACE commented 4 years ago

不要断点,一直用printf打印出来看吧,因为脏矩形会一直变的,你的意思是按钮指键盘上面的按钮?

FandelXiong commented 4 years ago

打印出来也是一样的,我的xml有自定义的数字键盘,就是点击上面的按钮;就算不是透明的窗体也是一样的,少数胀矩形是正确的,大多数时候都是1080p

WNsACE commented 4 years ago

但是我看这个 xml 中也没有什么特别的地方,你用的是 awtk-linux-fb 的是适配层么?

WNsACE commented 4 years ago

代码可以发出来么?

FandelXiong commented 4 years ago

整个工程的代码吗

WNsACE commented 4 years ago

又或者你可以试一下只通过 window_open 打开这个 xml,然后就不执行其他的代码,看一下是不是代码引起的

FandelXiong commented 4 years ago

是的,这样胀区域,就是正确的,忘记了,原来的代码按钮按下时,有几个label也会变,但不至于整个屏幕的画面都变化;我把代码给你分析下 AwtkApplication1.tar.gz

WNsACE commented 4 years ago

我这边编译不了项目,你可以删除一些代码试试看,脏矩形机制是是把所有脏的区域合并在一起的,比如说左上角脏了一个像素点和右下角脏了一个像素点,合并在一起,脏矩形区域就是整个屏幕了

WeSrc-Yin commented 4 years ago

我使用的是双buffer,没有开启脏矩形算法,没有发现这个问题。@FandelXiong 另外,请教个问题@WNsACE, 你说的硬件加速打开宏WITH_G2D,我不清楚我的硬件可不可以硬件加速,那么,我自行定义WITH_G2D宏,会有问题吗?或者说怎么知道我的硬件是不是支持硬件加速?