melis中disp驱动问题
-
现在D1上将melis跑起来了,底层disp驱动也能点亮屏。
遇到下面两个问题想请教一下:- disp驱动如何进行帧同步刷新?
- disp驱动要显示一帧图像就是调用disp_ioctl(DISP_LAYER_SET_CONFIG, (void *)arg); ,请问上层如何知道显示一帧结束从而继续显示下一帧并释放资源?
-
@geniusgogo 在 melis中disp驱动问题 中说:
disp驱动要显示一帧图像就是调用disp_ioctl(DISP_LAYER_SET_CONFIG, (void *)arg); ,请问上层如何知道显示一帧结束从而继续显示下一帧并释放资源?
1.依赖TCON中断,TCON终端频率就是通常我们玩游戏的时候理解的刷新率。
2.这是由软件决定的,软件控制的叫帧率,也就是产生图像的频率,图像来源可以是GPU绘制合成的,也可以是来自于VPU解码送过来的,总之,这个帧率是方案决定的。
上层不知道一帧何时开始,何时结束的,上层只需要送帧.由TCON负责同步。你送的帧不一定马上显示出来,要等TCON中断过来,才会真正显示到屏幕上的。
所以你要结合刷新率考虑帧率,帧率上去了,刷新率越大越好,帧率不能超过刷新率,图不变,同样的图刷新多少次,效果是一样的,用户感知不到,自己要有一个帧率的预估,帧率一般由片源决定的,比如30FPS,60FPS等等,帧率要小于刷新率,大于刷新率的帧率是没有意义的。
3.搞清楚这两个”率",帧率和刷新率要配合,而这个配合,是你要觉察的。 -
@caozilong 在 melis中disp驱动问题 中说:
只需要送帧.由TCON负责同步。你送的帧不一定马上显示出来,要等TCON中断过来,才会真正显示到屏幕上的。
所以你要结合刷新率考虑帧率,帧率上去了,刷新率越大越好,帧率不能超过刷新率,图不变,同样的图刷新多少次,效果是一样的,用户感知不到,自己要有一个帧率的预估,帧率一般由片源决定的,比如30FPS,60FPS等等,帧率要小于刷新率,大于刷新率嗯,感谢解答。
不过依然还有个疑问,送一帧下去后可能上层有开始要送第二帧,如果没法知道底层是否刷完的话,会造成花屏吧? 因为不知道底层刷没刷完。 -
@geniusgogo 不会的,驱动内部对显示图层分配了两个buffer,你可以认为是一个pingpong buffer机制,当前写的不是正在显示的那片buffer,两个buffer依赖TCON中断进行同步。
虽然不存在花屏的问题,但是可能存在覆盖的问题,如果你送帧的帧率和TCON刷新率不匹配(太快),可能会覆盖上次还没显示出来的帧。
比如你的帧率要控制在30fps,你就需要通过某种机制保证在这个范围内送帧,误差不要太大, 这方面RTOS做的要比linux 好很多。 -
@caozilong 在 melis中disp驱动问题 中说:
分配了两个buffer,你可以认为是一个pingpong buffer机制,当前写的不是正在显示的那片buffer,两个buffer依赖TCON中断进行同步。
虽然不存在花屏的问题,但是可能存在覆盖的问题,如果你送帧的帧率和TCON刷新率不匹配(太快),可能会覆盖上次还没显示出来的帧。
比如你的帧率要控制在30fps,你就需要通过某种机制保证在这个范围内送帧,误差不要太大, 这方面RTOS做的要比linux 好很多。好的明白了,谢谢!
-
@caozilong 再请教一个问题,就是假如上层开辟了一个全局静态的framebuffer,所有的帧数据都是通过这个同一个地址设置到layer里去的,那这样在disp驱动内部会实现拷贝到内部的pingpong buffer吗?还是只是记录一个指针? 如果记录的是上层传的指针就有可能虽然地下是双buffer指针,但其实是指向一个buffer,从而花屏。
-
@bookos buffer是零拷贝,驱动内部记录是乒乓指针,buffer由应用去分配。
所以,站在这个层面看显示驱动,你不能只分配一个静态framebuffer,而是至少分配两个,然后传指针进去. -
@caozilong 在 melis中disp驱动问题 中说:
@bookos buffer是零拷贝,驱动内部记录是乒乓指针,buffer由应用去分配。
所以,站在这个层面看显示驱动,你不能只分配一个静态framebuffer,而是至少分配两个,然后传指针进去.那这样的话,我又有一个疑问了,问题又回到最初的那个问题“应用不知道底层现在正在刷哪个buffer” 从而可能花屏。
例如:应用分配buffer A/B,第一次显示buffer A,第二次显示buffer B,第三次由于应用不知道前两次显示的是否完成,所以按照应用层交替使用A/B buffer的逻辑,此时又会使用A,而此时底层驱动可能正在刷A,这就导致应用也会同时修改A buffer的数据,造成不同步花屏。
-
@geniusgogo 在 melis中disp驱动问题 中说:
例如:应用分配buffer A/B,第一次显示buffer A,第二次显示buffer B,第三次由于应用不知道前两次显示的是否完成,所以按照应用层交替使用A/B buffer的逻辑,此时又会使用A,而此时底层驱动可能正在刷A,这就导致应用也会同时修改A buffer的数据,造成不同步花屏。
有可能的。
buffer的指针在用户手里,用户如果不加考虑随便写,可能会导致写入正在显示的画面,导致撕裂。
以播放视频的场景为例,一般video framebuffer会有很多个,比如说10个吧,所以显示那边会有一个显示帧队列,比如有三个帧,一帧是刚刚获取的,一帧是正在显示的,还有一帧是刚刚显示完的,通过软件控制时序,是可以保证常态化如此的,你可以理解它有点类似于网络中的滑动窗口,队列中永远都有一个待显示帧,当前帧和已显示帧。并且已显示帧需要回帧后,解锁才能再次写入数据,这样就可以避免撕裂的情况。
如果是UI framebuffer,也可以参考类似的做法,多创建几个帧,并且创建回帧机制。
严谨的做法可能要用到fence机制了,如果你们有 tina sdk,在disp2驱动下有个composoer_init函数,里面的逻辑就是实现fence的,安卓上用的就是这套机制。所以,你说的情况是存在的,但是如果你隔足够安全的时间去送帧,自然每次都是成功的,这也是melis上的做法。
-
@geniusgogo 或者你了解到的方案中有其它更好的实现方式,也可以给我们推介一下.
-
@caozilong 在 melis中disp驱动问题 中说:
@geniusgogo 或者你了解到的方案中有其它更好的实现方式,也可以给我们推介一下.
如果disp驱动能将帧同步中断回调开放,并在回调里通知当前正在使用的用户buffer指针,UI framebuffer就能根据这个回调来判断是否可以送下一帧数据,并且可以实现多buffer切换。
类似是底层回调如下接口:void sync_event(void *current_buffer, void *prev_buffer) { }
current_buffer代表正在准备显示的buffer,prev_buffer代表已经显示完的buffer。
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号