I need to create a C++ function that will return the number of seconds until the next Vsync interval as a floating point value.
Why?
I am creating programs that display rectangles that follow the mouse cursor. Ostensibly OpenGL provides a vsync mechanism in the glXSwapBuffers function, but I have found this to be unreliable. With some card drivers you get vsync; with others you don't. On some you get vsync but you also get an extra 2-frames of latency.
But this is not a bug in OpenGL. The spec is intentionally vague: "The contents of the back buffer then become undefined. The update typically takes place during the vertical retrace of the monitor, rather than immediately after glXSwapBuffers is called." The key word being "typically"... basically glXSwapBuffers doesn't promise squat w.r.t. vsync. Go figure.
In my current attempt to solve this basic problem, I currently guess an initial vsync time and then afterwords assume the phase equals elapsed time MOD 1/(59.85Hz) which seems to sync up with my current monitor. But this doesn't work so well because I don't actually know the initial phase. So I get one tear. At least it doesn't move around. But what I really need is to just measure the current vsync phase somehow.
No, I don't want to rely on some OpenGL call to do a vsync for me. Because of the vagueness in the spec, this gives the OpenGL implementation to add as much latency as it pleases.
No, I don't want to rely on some SGI extension or some other thing that has to be installed to make it work. This is graphics 101. Vsync. Just need a way to query its state. SOME builtin, always-installed API must have this.
Maybe I can create a secondary thread that waits for Vsync somehow, and records the time when this happens? But be aware that the following sequence:
#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));
}
does NOT work in Debian. Result:
% ./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
There must be some way to just read the phase from a device, or some other OpenGL call. OpenGL is THE THING for graphics. Vsync is graphics 101.
Please help.
/dev/fb0
exists in your environment in 1st place, and theopen()
call went OK? – Annalisaannalise