我正在用C语言制作一个在linux帧缓冲区上运行的游戏。到目前为止,我有一个红色的100x100正方形,它和鼠标一起移动,就像一个指针。我已经实现了双缓冲,它工作正常(正方形不会闪烁)。问题是,有相当多的撕裂水平发生。我的意思是,当正方形在x轴上移动时,它就像被水平分割,其中一部分比另一部分向前滑动得更多。如果我继续移动,这种"撕裂"在正方形上从上到下缓慢传播。
我相信发生这种情况是因为当我将双缓冲区复制到主缓冲区时,硬件会读取帧缓冲区。
我曾试图用FBIO_WAITFORVSYNC ioctl解决这个问题,但没有成功。
有什么想法可以在帧缓冲区上进行VSync吗?请在你的解释中添加细节,因为这是我第一次在基于Linux的操作系统上编程这样的东西,所以我可能无法理解其他情况。
这是我的代码:http://pastebin.com/KJ4iaVEL
这不是进行双重缓冲的正确方法。您在后台缓冲区上完成所有绘制是正确的,但随后您执行memcpy将数据传输到前台。在复制过程中,屏幕刷新很容易发生。
要正确执行此操作,您只需要切换指向数据的指针;而不是复制数据本身。对于Linux帧缓冲区设备,这是通过拥有一个两倍于物理屏幕的"虚拟"屏幕来实现的,并使用偏移变量来设置显示上半部分还是下半部分。您可以使用FBIOGET_VSCREENINFO
、FBIOPUT_VSCREENINFO
和FBIOPAN_DISPLAY
ioctl
调用来查询大小和设置偏移量。
本页简要介绍了有关此方面的一些详细信息:http://www.ummon.eu/Linux/API/Devices/framebuffer.html
所有相关的数据结构都在linux/fb.h
头文件中。
不幸的是,我很难理解@Steven Bell的答案不太正确。尽管他说屏幕刷新在记忆过程中很容易发生是对的,但正确的解决方案并不是像许多线程所建议的那样,创建一个两倍于屏幕大小的虚拟帧缓冲区并在它们之间平移。任何尝试此解决方案的人都会收到此处描述的错误:在fb_var_screeninfo中设置yres_virtual时出现无效参数错误。
每个线程:https://forum.odroid.com/viewtopic.php?f=55&t=8741不太可能真正对帧缓冲区进行双重缓冲(/dev/fb0,尽管我听说树莓PI可能是这个规则的例外)。但这并不意味着没有办法在linux中使用低级别图形来加倍缓冲区。
这里真正的解决方案是使用libdrm(/dev/dri/card0)在屏幕上绘制低级图形。这里有一个非常好的例子来说明如何做到这一点:https://github.com/dvdhrm/docs/blob/master/drm-howto/modeset-vsync.c当我试图解决这个问题时,我使用了自己。
无论如何,我希望我已经救了一个人,我必须经历的惊人的头痛,以解决未来的问题。