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

标签 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,但“无效参数”错误并没有消失。

我也试过根据这个人的建议映射一个更大的缓冲区: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!");

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

最佳答案

我解决 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 平台上运行良好。

关于c - 使用 linux framebuffer 进行适当的双缓冲,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49657086/

相关文章:

c - 将 JPEG 屏幕截图保存为 C 中的 BYTE 缓冲区

linux - 如何利用硬件参数唯一标识一个设备?

OpenGL:渲染到纹理和帧缓冲对象的问题

c++ - 如何使用渲染缓冲区和 glBlit 渲染到四个窗口,使用 GLFW

c++ - 纹理单元重叠?渲染了错误的纹理

c - "What this value exactly equal to?"

c - 在包装n个最大容量为W的箱子时,要最小化箱子的数量,同时还要将浪费的箱子空间最小化?

c - 为什么我们不能在 Linux 中通过 system() 系统调用更改目录?

linux - 我该如何为usermod制作一个shell脚本

c - 关于使用 SIGKILL 的说明