Linux 帧缓冲图形和 VSync

Posted

技术标签:

【中文标题】Linux 帧缓冲图形和 VSync【英文标题】:Linux framebuffer graphics and VSync 【发布时间】:2012-12-16 14:10:16 【问题描述】:

我正在用 C 语言制作一个在 linux 帧缓冲区上运行的游戏。到目前为止,我有一个红色的 100x100 正方形,它与鼠标一起移动,就像一个指针一样。我已经实现了双缓冲并且它工作正常(正方形不闪烁)。问题是,横向发生了很多撕裂。我的意思是,当正方形在x轴上移动时,就像它被水平分割,它的一部分比另一部分进展得更快。如果我继续移动,这个“裂口”会在广场上从上到下缓慢传播。

我相信这是因为硬件在我将双缓冲区复制到主缓冲区的那一刻读取帧缓冲区。

我已尝试使用 FBIO_WAITFORVSYNC ioctl 解决该问题,但没有成功。

有什么想法可以在帧缓冲区上进行垂直同步吗?请在您的解释中添加详细信息,因为这是我第一次在基于 Linux 的操作系统上编写此类内容,因此我可能无法理解。

这是我的代码:http://pastebin.com/KJ4iaVEL

【问题讨论】:

您使用什么视频硬件?例如,Linux 在 Sandy Bridge 英特尔显卡方面存在撕裂问题。请澄清。 @vorbote 我有一个 Nvidia 7800 GTX,抱歉没有提到。正常使用没有撕裂(例如当我在 X 中移动窗口时)。 【参考方案1】:

这不是进行双缓冲的正确方法。您在后台缓冲区上进行所有绘制是正确的,但随后您执行 memcpy 将数据传输到前面。在复制过程中很容易发生屏幕刷新。

要正确执行此操作,您只需切换指向数据的指针;不复制数据本身。对于 Linux 帧缓冲设备,这是通过拥有一个两倍于物理屏幕的“虚拟”屏幕并使用偏移变量来设置您是显示上半部分还是下半部分来完成的。您可以使用FBIOGET_VSCREENINFOFBIOPUT_VSCREENINFOFBIOPAN_DISPLAY ioctl 调用来查询大小和设置偏移量。

此页面简要介绍了有关此的一些详细信息:http://www.ummon.eu/Linux/API/Devices/framebuffer.html

所有相关的数据结构都在linux/fb.h头文件中。

【讨论】:

链接已失效... :-( Wayback 机器来救援! web.archive.org/web/20180702063450/http://www.ummon.eu/Linux/…【参考方案2】:

不幸的是,我很难理解@Steven Bell 的回答并不完全正确。尽管他是正确的,在 memcpy 期间很容易发生屏幕刷新,但正确的分辨率不是创建一个两倍于屏幕大小的虚拟帧缓冲区,并在它们之间平移,正如许多线程所暗示的那样。尝试此解决方案的任何人都会收到此处描述的错误:invalid argument error when setting yres_virtual in fb_var_screeninfo。

根据这个线程:https://forum.odroid.com/viewtopic.php?f=55&t=8741 不太可能真正双缓冲帧缓冲区(/dev/fb0,尽管我听说树莓派可能是这个规则的一个例外)。但这并不意味着没有办法在 linux 中使用低级图形来加倍缓冲区。

这里真正的解决方案是使用 libdrm (/dev/dri/card0) 将低级图形绘制到屏幕上。这里有一个很好的例子来说明如何做到这一点:https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c,我在尝试解决这个问题时使用了自己。

无论如何,我希望我已经避免了我在未来解决这个问题时必须经历的令人头疼的问题。

【讨论】:

以上是关于Linux 帧缓冲图形和 VSync的主要内容,如果未能解决你的问题,请参考以下文章

使用 linux 帧缓冲区进行图形但禁用控制台文本

计算机图形学(OPENGL):帧缓冲

防止 OpenGL 缓冲帧

帧缓冲子系统框架

Android 图形系统(2)---- Android vsync 机制与 project buffer

帧缓存的详细介绍