我需要创建一个 C++ 函数,它将返回到下一个 Vsync 间隔的秒数作为浮点值。
为什么?
我正在创建显示跟随鼠标光标的矩形的程序。表面上,OpenGL 在 glXSwapBuffers 函数中提供了一个 vsync 机制,但我发现这是不可靠的。使用某些卡驱动程序,您可以获得 vsync;与其他人你不。在某些情况下,您会获得 vsync,但也会获得额外的 2 帧延迟。
但这不是 OpenGL 中的错误。规范故意含糊其辞:“后台缓冲区的内容然后变得未定义。更新通常发生在监视器的垂直回溯期间,而不是在调用 glXSwapBuffers 之后立即发生。” 关键词是“通常”......基本上glXSwapBuffers 不承诺蹲wrt vsync。去搞清楚。
在我目前解决这个基本问题的尝试中,我目前猜测初始垂直同步时间,然后假设相位等于经过时间 MOD 1/(59.85Hz),这似乎与我当前的显示器同步。但这并不奏效,因为我实际上并不了解初始阶段。所以我得到一滴眼泪。至少它不会四处走动。但我真正需要的是以某种方式测量当前的 vsync 相位。
不,我不想依赖一些 OpenGL 调用来为我做一个 vsync。由于规范中的含糊不清,这使得 OpenGL 实现可以随心所欲地增加延迟。
不,我不想依赖某些 SGI 扩展或其他一些必须安装才能使其工作的东西。这是图形 101。Vsync。只需要一种查询其状态的方法。一些内置的、总是安装的 API 必须有这个。
也许我可以创建一个以某种方式等待 Vsync 的辅助线程,并记录发生这种情况的时间?但请注意以下顺序:
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/fb.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{
int fb = open("/dev/fb0", O_RDWR);
assert(fb != -1);
int zero = 0;
if (ioctl(fb, FBIO_WAITFORVSYNC, &zero) == -1)
printf("fb ioctl failed: %s\n", strerror(errno));
}
Run Code Online (Sandbox Code Playgroud)
在 Debian 中不起作用。结果:
% ./a.out
fb ioctl failed: Inappropriate ioctl for device
% ls -l /dev/fb0
crw-rw-rw- 1 root video 29, 0 Sep 1 20:52 /dev/fb0
Run Code Online (Sandbox Code Playgroud)
必须有某种方法可以从设备或其他一些 OpenGL 调用中读取相位。OpenGL 是图形的重点。Vsync 是图形 101。
请帮忙。
当您搜索FBIO_WAITFORVSYNC
Linux 内核源代码时,您可以看到它仅针对少数显卡实现,而不是针对所有显卡。
因此,如果您碰巧拥有许多其他卡中的一张,您会收到“设备的 ioctl 不合适”,这意味着该显卡驱动程序未实现。
也许如何在 Xlib 应用程序中等待 VSYNC?给你一些正确方向的提示。