我需要创建一个 C++ 函数,它将在下一个 Vsync 间隔之前的秒数作为浮点值返回。
为什么?
我正在创建显示跟随鼠标光标的矩形的程序。表面上,OpenGL 在 glXSwapBuffers 函数中提供了一个 vsync 机制,但我发现这并不可靠。使用一些卡驱动程序,您可以获得 vsync;与其他你没有的人。在某些情况下,您会获得垂直同步,但您也会获得额外的 2 帧延迟。
但这不是 OpenGL 中的错误。规范故意含糊不清:“后台缓冲区的内容然后变得未定义。更新通常发生在监视器的垂直回溯期间,而不是在调用 glXSwapBuffers 之后立即发生。” 关键字是“典型地”......基本上glXSwapBuffers 不承诺squat wrt vsync。去搞清楚。
在我目前解决这个基本问题的尝试中,我目前猜测初始 vsync 时间,然后假设相位等于经过时间 MOD 1/(59.85Hz),这似乎与我当前的监视器同步。但这并不好用,因为我实际上并不知道初始阶段。所以我得到一滴眼泪。至少它不会四处走动。但我真正需要的是以某种方式测量当前的垂直同步阶段。
不,我不想依赖一些 OpenGL 调用来为我做垂直同步。由于规范中的模糊性,这使得 OpenGL 实现可以根据需要添加尽可能多的延迟。
不,我不想依赖某些 SGI 扩展或必须安装的其他东西才能使其工作。这是图形 101。垂直同步。只需要一种查询其状态的方法。某些内置的、始终安装的 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));
}
在 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
必须有某种方法可以从设备或其他 OpenGL 调用中读取相位。OpenGL是图形的东西。Vsync 是图形 101。
请帮忙。