Work-around for no Vsync in windowed mode?

I’ve been experimenting with determining the phase & period of the vsync signal (by timing a tight redraw loop in fullscreen exclusive mode),
with the idea of using this information to accurately time repaints in windowed mode to minimize or even eliminate tearing.

Timing the phase & period of the vsync has been easy enough, but… (yes, the inevitable but… :slight_smile:
The actual refresh rates i’m measuring do not (quite) correspond with the refresh-rate the display is supposed to be operating at (according to Windows).

I’m using an hdtv as my monitor, and these are the values i’m observing for the different refresh rates my screen supports.


Reported : Observed
24Hz       : 23.974257Hz -> 23.97Hz ?
25Hz       : 24.99952Hz -> 25Hz
30Hz       : Barfs
50Hz       : 49.99325Hz -> 50Hz
60Hz       : 59.93889Hz -> 59.94Hz ?

I realize that the way in which i’m collecting the timings (System.nanoTime()) has it’s own error margins involved.
However, the results clearly point to the fact that for 24Hz & 60Hz the drivers are reporting my refresh rate to be one value - where-as in reality it is something different.

Another problem is that i’m observing drift in the results, now my understanding of the vsync signal is that it’s regular as clockwork. Is this a false assumption?
Or is it, as I suspect System.nanoTime() that is drifting. (though, it could be something wrong with my code too…)

It’s really the drift that’s stopping this experiment from getting any further; but the false reporting of the refresh-rate intrigued me enough
to see if anyone else had encountered, or even considered that the OS might be lying to you! ;D

:EDIT:

I might hook up one of my 19" monitors & see what that reports for ‘60Hz’.

Here’s what I get when analysing my 19" monitor:


@60 -> 60.015537Hz
@72 -> 71.99875Hz
@75 -> 75.020294Hz
@76 -> 75.95719Hz

It doesn’t appear to be any great revelation that the refresh rates reported by the OS are only approximations; but isn’t it then wrong to base game logic at a rate that does not match the display rate?

You see many games dropping into resolution X by Y @ 60Hz, and then running their game logic @ exactly 60Hz - expecting the two to stay in-sync.
If using v-sync to throttle the game, the game speed will vary +/-0.5% depending upon the actual refresh rate being used by the game.
If not using v-sync, then you’ll get 1 duplicate or dropped frame once every ~200 seconds.

I’m aware this issue is particularly important in decoding & syncing audio & video streams (the whole 24p/100Hz/2:3 pulldown etc etc),
but hadn’t considered that it also effects games to some degree too.

Basically, fixed frame time really is flawed even for 2D - because refresh rates cannot be relied upon as being precise.

Also, for games that use DirectX, have a fixed time step & rely upon v-sync to throttle the game speed - there appears to be a really interesting way of cheating.

start->run->dxdiag->‘more help’ tab->‘override…’ button-> force refresh rate->40Hz

It’ll be like playing the game @ 2/3 speed =)

Weird results!

There’s a bug about the lack of v-sync here: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6378181

Dmitri Trembovetski of java2D fame has promised to make a fix in time for java7.

Unfortunately this still haven’t happened as I’m on the JavaFX gfx team pretty much 100% of my time =(

There’s already vsync support in the jdk (as of 6u10 or so), but only signed apps will be able to use it (it involves the use of a private BufferCapabilities subclass): http://hg.openjdk.java.net/jdk7/2d/jdk/file/a389af17df10/src/share/classes/sun/java2d/pipe/hw/ExtendedBufferCapabilities.java

Dmitri

this is a noob question

but why isn’t the BufferStrategy capable of eliminating tearing in Window Mode as is in FSEM?

in the docs ( http://java.sun.com/javase/6/docs/api/java/awt/image/BufferStrategy.html ) it doesnt say anything about using it only in FSEM (though there is an example along the FSEM tutorial link: http://java.sun.com/docs/books/tutorial/extra/fullscreen/index.html )

In full screen mode, if the Direct3D pipeline is enabled, BufferStrategy defaults to vsync-ed mode because it is assumed that most full screen apps are games or apps which need smooth user experience. In windowed mode typically responsiveness is more important, which is why BS is not v-synced by default for windowed apps (which includes swing since it uses buffer strategy for double buffering).

So yes, buffer strategy is capable of being v-sync-ed in windowed mode (providing a hw accelerated pipeline is used), but by default it isn’t v-synced.

Dmitri

all this talk about “default” gave me the impression that the programmer can use the BS class the way he wants to -for example, not v-sync while in FSEM or v-sync while in window mode (by calling methods of the BS class perhaps?)

or is the default behavior the only behavior possible provided by Java??

thank you for your time Dmiitri

Right now “default” means that if you create a BS in FSEM mode, it’ll be v-synced, in windowed mode - non-vsynced.

In jdk7 the intention was to add a new API (specifically, a BufferCapability variant which specifies what kind of BufferStrategy to create) which would allow to override the default behavior and request vsync-ed or non-vsync-ed strategy.

Dmitri

thank you very much for your time

i think i got it now…

This looks great, nice work solving it with this new class. It would be great to get it included in java7. Could you justify working on it since javaFX relies on the java2D API? Thanks for keeping us informed!

Cheers,
Keith

Well, the FX runtime can use this private API anyway (since the java fx runtime is signed). It was in fact added for this very purpose (FX support), so it will be hard to justify spending more time on it to make it a public API.

The main issue with making this a public API is not in coding but clarifying all sorts of “ifs and buts” etc since we can’t guarantee that it can be enabled in all cases (so that apps start relying on it for say driving their animation etc). Also, there are some restrictions on how this can be used in applets - with the current AWT/2D model it’s hard to make it such that vsync-ed applets within same app don’t affect each other’s framerate (they’ll basically get half of the frame rate if two of them running on a page).

Dmitri

That’s a pity, but at least it’s in there as a private API.

Thanks Dmitri

Do a singed application apply to applets/webstart apps only? Or do I must sign a standalone applications as well, I think its not necessary right?

What comes to the to-be-or-not public api debate. Well is it so much a problem if some systems cannot use it. Graphics and game developers are used to it anyway each gfx cards have own issues to tackle. Publish it with a disclaimer it may not work so check for capability mode after setting it.

I had a need to program a silk smooth image scroller, from right to left, in windowed application and eating <5% cpu. It was a mission impossible in Java, cpu was ok but animation was not even close to an acceptable level. In the end had to use Delphi and directx application :frowning:

Maybe this private api could have helped me. I must take time create a test program someday and see if there is still hope in Java.

thx.

Standalone apps run with all permissions.

Cas :slight_smile:

You could have just used one of the many Java OpenGL bindings or libraries, like LWJGL, JOGL, Slick and just got vsync and super smoothness that way.