使用linux framebuffer进行适当的双缓冲

时间:2018-04-04 17:33:15

标签: c linux framebuffer double-buffering

我想知道如何正确地双重缓冲帧缓冲以避免撕裂。我已经对这个主题进行了大量研究,似乎找不到任何东西。

我尝试过FBIO_WAITFORVSYNC。但根据这个帖子:How to query Vsync phase in Linux似乎这不起作用。

我也尝试过使用FBIOGET_VSCREENINFO  和每个帖子的FBIOPAN_DISPLAY:Linux framebuffer graphics and VSync。但由于此主题中讨论的错误导致失败:invalid argument error when setting yres_virtual in fb_var_screeninfo

该线程建议使用不同的驱动程序(vesafb)来解决错误。我设法在我的机器上安装uvesafb,但“无效参数”错误没有消失。

我也试过根据这个人的建议mmaping一个更大的缓冲区:http://betteros.org/tut/graphics1.php#doublebuffer但是mmap一直返回-1。

我也试图实现这里讨论的解决方案:https://pyra-handheld.com/boards/threads/my-frustrating-experiences-with-dev-fb.21062/。然而,线程在没有发布实际解决方案的情况下死亡,我怀疑交换硬件地址的效率(或者甚至可以做到)。

对此主题的任何帮助都会非常感激!

由于请求,这里是我希望开始工作的代码:

fb0 = open("/dev/fb0", O_RDWR);
    if(fb0 == 0)
        error("Could not open framebuffer located in /dev/fb0!");

    if (ioctl(fb0, FBIOGET_FSCREENINFO, &screeninfo_fixed) == -1)
        error("Could not retrive fixed screen info!");

    if (ioctl(fb0, FBIOGET_VSCREENINFO, &screeninfo_var) == -1)
        error("Could not retrive variable screen info!");

    screeninfo_var.xres_virtual = screeninfo_var.xres;
    screeninfo_var.yres_virtual = screeninfo_var.yres * 2;
    screeninfo_var.width = screeninfo_var.xres;
    screeninfo_var.height = screeninfo_var.yres;
    screeninfo_var.xoffset = 0;
    screeninfo_var.yoffset = 0;

    if (ioctl(fb0, FBIOPUT_VSCREENINFO, &screeninfo_var) == -1)
        error("Could not set variable screen info!");

这将始终打印“无法设置变量屏幕信息!”由于某些问题扩展了虚拟帧缓冲区大小。

1 个答案:

答案 0 :(得分:0)

我解决了Linux上帧缓冲的双重缓冲问题的方法是使用单独的后备缓冲,使用mmap将其分配给相同的屏幕尺寸:

bbp = mmap(0, screensize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

(其中screensize = vinfo.yres_virtual * finfo.line_length;

然后将所有更改都写入此后台缓冲区,并在所有写入结束后,使用一个update()函数将整个后台缓冲区复制到主帧缓冲区指针位置:

memcpy(fbp, bbp, screensize);

您还可以具有只复制给定区域的updateRect()函数。在我的x64 PC gnu / linux平台上,此逻辑工作正常。