Well, good questions and I suspect that it's good questions like these have delayed proper vsync support in X:)
I guess every display should have its own vsynced double or triple buffer and the clients that care (most don't) should be able to get a maximum of one call-back per frame to do rendering for the next frame.
If the displays have different update rates and the window spans both displays, then I guess you're SOL:)
X: 25 years and still lacking vsync'ed double buffering
Posted Sep 28, 2009 18:01 UTC (Mon) by jzbiciak (✭ supporter ✭, #5246)
[Link]
If you want the same performance as triple buffering has on a single display (ie. the renderer is never blocked by vsync), for a window straddling N displays you would need N+2 buffers. With that, you can achieve the same non-blocking performance with an arbitrary number of displays.
On a flip, the application lets X know that the buffer just completed is the "most recent" and X can switch to an undisplayed buffer. Since there are N+1 buffers other than the one just completed, there is guaranteed to be at least one available buffer.
When each of the N displays reaches its vertical retrace, it pulls the "most recent" buffer at the time of its vertical retrace for the portion of the window covering that display. In the worst case (ie. a very fast application with an absurdly high frame rate displaying on N displays whose refresh rates are effectively relatively prime to each other, which could happen if they're all driven from separate crystals), all N displays could in fact be displaying their portion from different source frames. But, you won't get any shearing within each display.
You can decrease the buffering from there, sliding down a continuum of likelihood to block the application. The minimum buffering case is still the double buffer, but you have to wait for all displays to hit vertical retrace before the application can resume. Between 2 and N+2, you can have varying levels of "likelihood to block" while the application waits for at least one buffer to be undisplayed. Chances are, even with a largish N (such as, perhaps, a 25 display system arranged as a 5x5, with nominally the same refresh rate but driven from different crystals), performance shouldn't be too bad with as few as 4 buffers, since the displays are all flipping at about the same rate, particularly if your rendering rate isn't dramatically faster than your refresh rate.
X: 25 years and still lacking vsync'ed double buffering
Posted Oct 7, 2009 4:47 UTC (Wed) by pphaneuf (guest, #23480)
[Link]
I think the reason why there's no good vsync support in X is that you
can't hook interrupts from user-space, and they didn't want to poll,
because it would have made everything else suck.
Note that there's nothing in the X11 API that precludes using vsync to
avoid tearing without exposing it in the API. What you need is just for a
drawing command not to be in effect while the retrace is over the affected
area.
X could implement its drawing so that this doesn't happen in the
middle of one of its drawing commands, and you wouldn't get tearing.
Now, you might not want a partially drawn image, even if it does so without
any tearing. In that case, you can just do the double buffering yourself, by
drawing into a pixmap instead of directly in the window, and XCopyArea
the pixmap to the window when you're done (which is a single operation,
so could be done without tearing).
The only thing that would need an extension for is throttling, so that
you don't draw more than one image to your pixmap when only one copy
can be made to the window. What you'd want is a XCopyArea that would
send an event back to the client when it has been done. That can even
support two displays with different update rates, you'd just get the event
for different copies at a different rate, depending on where you put it.