VincentWei / MiniGUI

A modern and mature cross-platform window system for embedded systems and smart IoT devices.
http://www.minigui.com
GNU General Public License v3.0
676 stars 157 forks source link

您好,咨询一下shadow引擎旋转的问题 #111

Closed htk719809837 closed 1 year ago

htk719809837 commented 1 year ago

是这样的,现在fbcon加入了双缓存,我们从commlcd显示引擎切换到了fbcon, 但是,因为设备是横屏竖用的,所以我们通过shadow引擎对屏幕进行了旋转,

[system] gal_engine=shadow

[fbcon] defaultmode=800x600-32bpp double_buffering=true

{{ifdef _MGGAL_SHADOW

[shadow] real_engine=fbcon defaultmode=600x800-32bpp rotate_screen=ccw

}}

旋转后显示正常,但是触摸却不正常了,是不是shadow引擎旋转对触摸做了什么操作呢? 示意图如下所示:请问是否有解决方案呢 B44CE7E2-134D-4DE1-A2C1-FC1DEE97A728

VincentWei commented 1 year ago

Shadow 引擎默认会根据屏幕旋转的方向设置一个回调函数,用于对触摸屏的坐标进行同样的旋转操作,具体见如下代码:

https://github.com/VincentWei/MiniGUI/blob/master/src/newgal/shadow/shadow.c#L577

如果你的触摸屏不需要旋转,可以将这段代码注释掉,也就是确保 __mg_ial_change_mouse_xy_hook 为 NULL。

htk719809837 commented 1 year ago

可以生效,但是经过shadow引擎旋转后,原有的fb地址发生了变化,有没有办法拿到新的地址? 使用原有的fb地址抓取当前设备显示的内容,结果图片是花屏的

VincentWei commented 1 year ago

针对 HDC_SCREEN 调用 LockDC() 函数,获取地址后记得调用 UnlockDC() 函数:

https://github.com/VincentWei/MiniGUI/blob/master/include/gdi.h#L1983

htk719809837 commented 1 year ago

你好,有一个比较着急的问题; 是这样的,在以前的项目里,我们使用3.0配合commlcd进行显示; 但是5.0中对fb做出了优化,我们换到了fbcon,这里带来了一些问题 1、部分设备不支持double_buffering,使用这个属性以后,设备起不来,无法显示,这个是为什么呢? 2、fb是不是支持原生的旋转?包括坐标一起旋转?想绕过shadow提升性能 3、使用shadow对fb进行旋转后,设备性能有一定下降。这里的设备是横屏竖用,1024x600的屏幕通过shadow旋转成600x1024,通过对gfx信息的查看,可以看到设备其实只有592x1024,并不是600x1024,所以UI感觉像是从592展开到600,导致刷新存在严重的卡顿,这个是什么引起的呢?是不是有办法从600开始? 4、针对于第三个问题,如果使用commlcd(bsp层已经做好屏幕的旋转),应用层不使用shadow旋转,UI就是600x1024,不会是592x1024。而且刷新一定程度上会好一点。是不是shadow引擎目前还有问题呢?

VincentWei commented 1 year ago

双缓冲的原理是单独开一个缓冲区(一般称为离屏缓冲区,off-screen buffer)给 MiniGUI 用,然后将更新累积下来刷新到实际的缓冲区中。这一技术主要用来解决窗口内容的频繁刷新导致的屏幕闪烁问题。Shadow 引擎和 FBCon 的双缓冲区原理类似,但可以额外提供内容的旋转能力。但是,内容的旋转会多出水平像素到垂直像素的逐点复制过程,而且基本上没有太好的优化措施(用汇编指令可以在一定程度上改善),所以使用 Shadow 引擎获得屏幕内容的旋转功能时,会导致屏幕的刷新性能下降。也因为 Shadow 引擎已经使用了离屏缓冲区,因此,如果使用 Shadow 引擎,就没有必要再开启 FBCon 的双缓冲区,否则会导致不必要的两次刷新。

1、部分设备不支持double_buffering,使用这个属性以后,设备起不来,无法显示,这个是为什么呢?

引起这种现象的原因可能有多种因素,可以检查一下像素格式是不是不匹配,比如 Alpha 全部变成了 0。从实现原理上看,如果不使用双缓冲区屏幕的显示正常,开启双缓冲区就不正常,这就有点奇怪了。毕竟从离屏缓冲区到实际缓冲区的内容复制,本质上就是一个内存的复制过程,和 MiniGUI 当中的 BitBlt 操作几乎没区别。另外,也可以看看 FB 驱动程序那边是不是设计了一些额外的,需要调用的 ioctl 操作,用于主动通知 FB 设备内容有变化。我们在某些芯片平台上遇到过类似的问题。

2、fb是不是支持原生的旋转?包括坐标一起旋转?想绕过shadow提升性能

Linux 的 FrameBuffer 是一种非常简单的图形设备抽象设备驱动程序,除非自行定制自己的 FB 驱动程序,标准的接口中没有原生支持旋转的能力。但是,有时候底层的 display controller(显示控制器)可能会支持屏幕的旋转,如果显示控制器支持,则应该优先使用显示控制器的旋转功能,毕竟是硬件实现的。

3、使用shadow对fb进行旋转后,设备性能有一定下降。这里的设备是横屏竖用,1024x600的屏幕通过shadow旋转成600x1024,通过对gfx信息的查看,可以看到设备其实只有592x1024,并不是600x1024,所以UI感觉像是从592展开到600,导致刷新存在严重的卡顿,这个是什么引起的呢?是不是有办法从600开始? 4、针对于第三个问题,如果使用commlcd(bsp层已经做好屏幕的旋转),应用层不使用shadow旋转,UI就是600x1024,不会是592x1024。而且刷新一定程度上会好一点。是不是shadow引擎目前还有问题呢?

这个现象看起来应该是底层 FB 驱动程序的返回的设备信息有误导致的。比如本来屏幕的水平像素个数应该是600,结果得到的数据是592。这肯定会导致旋转的结果不正常。

htk719809837 commented 1 year ago

这边前续项目用的是fbcon,屏幕没有旋转过,竖屏竖用;后续项目涉及到旋转,我们这边有已经旋转好的显示驱动接口(这个接口老版本项目使用commlcd引擎可以直接刷到屏幕上,并且刷上去是已经旋转好的),那如果我要使用fbcon作为底层引擎,旋转和刷新的接口还是采用commlcd实现的这个驱动接口来实现,有没有什么具体的实现方法呢?

相等于MiniGui.cfg仍然配置fbcon引擎,但是fb内部的刷新方式,改为调用__commlcd_drv_update()函数

VincentWei commented 1 year ago

如果底层驱动已经处理了旋转,那理论上直接用 fbcon 就可以了,不需要再做额外处理才对。也就是说,fb驱动程序应该屏蔽这些细节,提供标准接口就可以用了。

如果是因为显示驱动程序没有提供标准的接口,而且还需要双缓冲区支持的话,那就需要增强一下 commlcd 引擎 ,在 commlcd 引擎中开一个离屏缓冲区,然后在 commlcd 的 update 方法中完成缓冲区到真实设备的刷新操作即可。

具体可参考如下代码:

https://github.com/VincentWei/mg-tests/blob/master/comm-engines/commlcd_ops.c

上面的代码,将离屏缓冲区中的内容保存到了一个 BMP 文件中。原理是一样的。