PDA

View Full Version : glSwapBuffer only after even field (interlaced display)



-Andy-
12-04-2015, 06:57 AM
How can a graphics app use or configure the OpenGL driver so that buffer swaps only occur after the even field is displayed in a system with an interlaced display? The xconfig file does specify +vb so the swap will happen only on a vertical sync but this doesn't distinguish between odd and even fields.

The problem that can occur is sometimes glSwapBuffer will be called from the drawing task during the odd field (this being the first field of an interlaced display) so the swap will happen at the next vsync. The display will then show the last display buffer on the odd lines and the next display buffer on the even lines.

For some applications this is useful, motion smoothing etc but in other cases the swap needs to happen only after both fields have been shown. There doesn't seem to be any info on configuring this but there must be standard methods that already exist? It might not be configured in OpenGL or via API arguments and instead it should be in the video driver, to signal a vsync to OpenGL either on every vsync or only even vsyncs?

Any info or pointers to the existing methods to solve this case?
Thanks
Andy

Osbios
12-06-2015, 06:55 AM
https://www.opengl.org/wiki/Swap_Interval (specifically GLX_EXT_swap_control or GLX_MESA_swap_control)
Or when using SDL2 there is SDL_GL_SetSwapInterval()

You can set swap interval to 2. So it only actually will swap every second vsync. But I'm not sure what will happen when you miss a vsync. It may then sync always to the wrong vsync until you miss a vsync again.

I also recall that there are some older GLX functions where you get access to a vsync counter. Used that to try to implement my own version of dynamic vsync. :)
That counter maybe useful to you to "hack" your own solution to that issue.

Osbios
12-06-2015, 07:14 AM
Fount the older stuff. GLX_SGI_video_sync (https://www.opengl.org/registry/specs/SGI/video_sync.txt)

It come with this two functions.

int glXGetVideoSyncSGI(uint *count);
int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count);

glXWaitVideoSyncSGI basically just behaved like a spinlock on glXGetVideoSyncSGI when I used it with fglrx. So my code using this ended up always having tearing on top of the screen. But maybe you can make something from it.

-Andy-
12-09-2015, 12:57 PM
https://www.opengl.org/wiki/Swap_Interval (specifically GLX_EXT_swap_control or GLX_MESA_swap_control)
Or when using SDL2 there is SDL_GL_SetSwapInterval()

You can set swap interval to 2. So it only actually will swap every second vsync. But I'm not sure what will happen when you miss a vsync. It may then sync always to the wrong vsync until you miss a vsync again.

I also recall that there are some older GLX functions where you get access to a vsync counter. Used that to try to implement my own version of dynamic vsync. :)
That counter maybe useful to you to "hack" your own solution to that issue.

Thanks Osbios. The swap interval could let me skip one vertical sync but the drawing task has loosely related to the video timing; sometimes it may need to skip a sync, other times not. The GLX_SGI_video_sync may work though, it will depend if the hardware supports this counter.

Andy

GClements
12-09-2015, 05:30 PM
How can a graphics app use or configure the OpenGL driver so that buffer swaps only occur after the even field is displayed in a system with an interlaced display?
One option is to use a software phase-locked loop. Record the system time on each return from glXSwapBuffers(), and note that the differences between successive timestamps are multiples of the frame interval (to within the granularity of the system clock). Given a set of pairs of (frame#, time), you can use linear least-squares regression to determine the interval and offset (i.e. frequency and phase) of the refresh. You can then use the system clock to schedule buffer swaps (be sure to call glFinish() first, so that glXSwapBuffers() doesn't have to).

(If you test this, you'll note that a "60 Hz" refresh is typically 60/1.001 = 59.94 Hz, as that's the NTSC standard).

However: you aren't going to be able to tell which field is even and which is odd (if you need a specific field rather than just consistency, you'll need to provide some means for the user to toggle the field). And the scheme won't work if the driver uses triple buffering.