Getting a VBL IRQ in OS X?

Sage
Posts: 1,234
Joined: 2002.10
Post: #1
Lots of abbreviations here. Smile Explanation below.

Okay, has anyone figured out a method of generating video updates *at the exact frequency of the display refresh rate*?

Typically, what GL sample code does is set up an NSTimer with an arbitrary rate, like "1.0/60" or "0.001". This is NOT SUFFICIENT for my needs. I want to figure out what the refresh rate of the main display is, and get my update method called at either *exactly* that rate, or *exactly one half* that rate.

Now, I can use CGDisplayCurrentMode() with kCGDisplayRefreshRate to try to figure out the display refresh rate, except it's broken-- for LCD displays it always returns zero.

If I am using a CRT, or I blindly guess "60" for my Powerbook's refresh rate, and create an NSTimer with that rate, I notice that the timer slowly drifts, depending on (complexity of update method + some random factor.) E.g. I'd have to set the timer to something like 60.0345 Hz to compensate for the drift, and that only works on an 800 Mhz machine, for one particular update method, and it still isn't exact.

So, what I really want is a VBL IRQ-- a hardware Interrupt ReQuest that occurs at every Vertical BLanking. On OS 9 you could set up a VBLTask to get (simple) animation done during VBL. There doesn't appear to be any such service in OS X???

Has anyone seen differently?



Note, the method used by some Apple sample code, setting an NSTimer to 0.001, relies on the GL context to block until VBL, effectively slowing down the update to the refresh rate. This is no good because I can't get an update at *half* the refresh rate. You could if kCGLCPSwapInterval worked with values > 1, as documented, but it doesn't. It's also broken, only 0 or 1 is accepted.
Quote this message in a reply
henryj
Unregistered
 
Post: #2
aglSetInteger( aglContext, aglSwapInterval, 1);
will sync to vbl. You are supposed to be able to have multiples of the refesh, but last time I looked that didn't work. Maybe it's fixed in 10.2.3.

Quote:Now, I can use CGDisplayCurrentMode() with kCGDisplayRefreshRate to try to figure out the display refresh rate, except it's broken-- for LCD displays it always returns zero.


This is correct. LCDs don't have a refresh.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
Why do you need to be able to do these bizarre things? It might help us suggest workarounds...
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #4
Quote:Originally posted by henryj
aglSetInteger( aglContext, aglSwapInterval, 1);
will sync to vbl. You are supposed to be able to have multiples of the refesh, but last time I looked that didn't work. Maybe it's fixed in 10.2.3.


Nope, still busted in 10.2.3. In addition, 10.2.3 appears to break VBL in windowed contexts COMPLETELY. Everything drawn by the window mangager (menus, dragging windows, scrolling, everything!) is tearing now on my TiBook. Full screen contexts (like, screensavers) still work. I can't believe Apple would break this!?

Quote:
This is correct. LCDs don't have a refresh.

That is incorrect. If my LCD didn't refresh, it would stay black.
It may not have a raster beam that travels left and right, from top to bottom, but it does have a refresh rate. And, AFAIK, that rate is fixed on laptops/DVI flat panels and user-selectable on analog-connected flat panels (like older 3rd party VGA connector flat panels that could display at multiple refresh rates.)

I can appreciate the argument of "the display device may not have a constant refresh rate, so we'll just return zero" since, at some point in the future, we may get some eInk type device that only refreshes when you ask it to, but AFAIK all currently shipping displays have a constant refresh rate. That rate should be queryable via an API. Even on a hypothetical eInk display, if the application asks for the refresh rate of the system, it should get some meaningful response (perhaps calculated depending on the available CPU and power saving modes), not zero.


Quote:Originally posted by OneSadCookie
Why do you need to be able to do these bizarre things? It might help us suggest workarounds...


Very simple: I want create smooth animation. In a window.

By "smooth animation" I mean "one update method call per display refresh". The update method needs to know the refresh rate in order to adjust animation parameters, in the case of a wanting a constant animation speed.

Hence, I need to know the refresh rate of the display, and I need a dependable way to be called every refresh.

The "one call per every two refreshes" is for the case where I decide that there are not sufficient available resources (CPU, GPU) to update every frame when the refresh rate is very high (for instance, an old G3 iMac running at 112Hz.)
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
VBL synch does not appear to be broken in windows on 10.2.3 for me. What hardware do you have?

The 1ms timer should work fine for you. You'll update as frequently as possible, which when synched to the VBL will be exactly a fraction of the refresh rate. You won't know in advance what fraction you're getting, but since you're doing time-based rather than frame-based animation (you are, right?), that shouldn't be a problem.
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #6
Oops, you already said TiBook. Sorry. Haven't used one of those with 10.2.3 installed yet.

LCD screens do have a refresh rate, but there's not necessarily any way even for the OS to know it, let alone usefully communicate it to the application. There's certainly no vertical retrace to draw in... There was a long discussion about this on either the mac-games-dev or the mac-opengl list. Look it up if you're interested.
Quote this message in a reply
Sage
Posts: 1,234
Joined: 2002.10
Post: #7
Quote:Originally posted by OneSadCookie
Oops, you already said TiBook. Sorry. Haven't used one of those with 10.2.3 installed yet.


So far this appears to happen on Radeon 7500 Mobility machines. It doesn't happen on a Radeon 9000 desktop (verified) or the 1Ghz TiBook (Radeon 9000 Mobility) (as reported in MacNN thread.) I also found that replacing the ATIRadeon.kext with the 10.2.2 version fixes the 2d tearing, but it breaks all 3d apps. Sigh.

Quote:
There was a long discussion about this on either the mac-games-dev or the mac-opengl list. Look it up if you're interested.


I've read the whole thread now. It was suggested in the thread by two Apple engineers that people log bugs about the issues, but there is no mention about the outcome. I posted a followup to the mac-games-dev list asking for a summary, since it's still a problem for me.
Quote this message in a reply
honkFactory
Unregistered
 
Post: #8
Another approach is to use an NSTimer set to fire at 1000 fps or some other high rate. On my older g4 this gives me a refresh rate of about 250 fps when I draw with opengl into an area of 640x480 pixels. Then if you are drawing sprites you can update every time or if you are drawing whole frames you could pick and choose which when you want to udpdate your image.
A.W.
Quote this message in a reply
Post Reply