VBL syncing...

Okay, perhaps someone can help:

I’m currently working on a OpenGL demo. The part I currently finished is a car (with environment mapping and much more fancy stuff) driving thru a whole city. Now my problem: The OpenGL render engine doesn’t seem to swap the buffers at VBL time. You can always see this frame A at the first 1/3 of the screen and at the rest of the screen you see frame B. I’m setting up AGL with AGL_DOUBLEBUFFER. Of course the demo runs full screen with the help of DSp. The problem occurs at my G3+RagePro/6mb and at a pal’s G4/RagePro128, so that it doesn’t seem to be some graphic board specific problem.
I also set the AGL_SWAP_INTERVAL to 1, which should allow the OGL engine to swap only once and at VBL time, as described at the AGL reference:

GLint myRefresh = 1;

aglSetInteger(vidAGLContext, AGL_SWAP_INTERVAL, &myRefresh);

Perhaps someone has an idea how to avoid this VBL sync problems???

That could be one for the mac-opengl list. What you should do to debug that command is maybe call aglGetInteger with the AGL_SWAPINTERVAL to see if it is set right after you gave the command in that routine.

I was trying a similar thing lately and everybody on the list told me to do it the way you did. So I cannot see any prolem with that.

If you find out that the value is right, maybe something else is creating that problem.


The value is set right (the demo runs at 67 fps [or the approriate VBL frequency, of the resolution, that was choosen at the settings dialog] and not faster if the value is set to 1 and I disable my timing functions). Of course i checked the value with aflGetIntger() already, after trying aglSetIntger(). So the solution has to be anywhere else. Perhaps there is some other AGL setup method for better VBL accuracy? btw i watched at some DSp+OGL demos that are floating around (mostly some primitive cubes with textures and so on) and they suffer from the same ugly VBL artifact. Perhaps there is an issue with the opengl drivers, which apple isn’t aware of (I’m using v1.1.3)?

At this time the AGL_SWAP_INTERVAL integer
is ignored from the current AGL implementation, that’s wat i read from
the apple-opengl mailing list from an apple

The only way to get in sync with the monitor
is to install a VBL interrupt using the routines found in <retrace.h> , also you
should make shure you call glFinish(); before
calling aglSwapBuffers.

The AGL_SWAP_INTERVAL value is not ignored. I tried a cube with value 0. FPS was much greater than 100FPS. After setting the AGL_SWAP_INTERVAL value to 1, the FPS was triggered down to the frequency of the actual monitor frequency, e.g. 67hz (=FPS).

At the moment I’m using for timing purposes (frame skip, frame trigger) an installed VBL interrupt. Shall I call aglSwapBuffers() from within the interrupt function??? I don’t think that this is a good idea. My actual timing function waits until at least one or the next (because of frameskip) VBL has occured. immediately after this i call aglSwapBuffers(). I don’t think there is something wrong with it. I also played around with calling aglSwapBuffers() at diffrent positions within my code. glFinish() is alread called before my timing function. This can’t be the problem.

I’m getting insane… that’s the price you have to pay for coding with some high level api like OpenGL instead of doin it the hard way via direct hardware calls :wink:

I wonder if aglSwapBuffers is returning before it is finished drawing the back buffer? It is not because old drawing commands are still happening, because I think it implicitly calls glFinish before drawing the buffer.

If so, try calling aglSetcurrentcontext(null) after calling aglswapbuffers, and then at the beginning of your draw loop, put aglsetcurrentcontext(mycontext).

Just a wild guess. Below there is also an equivalent routine to swapbuffers, but it may work slower. You’ll need to change the rect values.

//quasi-equivalent to aglSwapbuffers?
glFinish(); //wait for drawing commands to stop
if (glIsEnabled(GL_DITHER)) //p.676 of red book
glReadBuffer(GL_BACK); //we’ll be copying pixels from back buffer
glDrawBuffer(GL_FRONT); //to the front buffer

//set draw position at lower-left hand corner
glCopyPixels(bottom,left,width, height,GL_COLOR); //copy rect to front

if (dither) glEnable(GL_DITHER);

“If so, try calling aglSetcurrentcontext(null) after calling aglswapbuffers, and then at the beginning of your draw loop, put aglsetcurrentcontext(mycontext).”

Oops, that still wouldn’t work. The next draw loop would just re-establish the context and start drawing even if the buffers are still being swapped maybe?

The next draw loop would just re-establish the context and start drawing even if the buffers are still being swapped maybe?

Directly from AGL_Reference.pdf:


aglSwapBuffers exchanges the front and back buffers of the current drawable. The exchange typically takes place during the vertical retrace of the monitor, rather than immediately after aglSwapBuffers is called. All AGL rendering contexts share the same notion of which are front buffers and which are back buffers.

An implicit glFlush is done by aglSwapBuffers before it returns. Subsequent OpenGL commands can be issued immediately after calling aglSwapBuffers, but are not executed until the buffer exchange is completed."

So what says this? This description tells us that the buffers are exchanged DURING the virtual retrace (at least if AGL_SWAP_INTERVAL is set to 1). But this does not happen. Either the AGL documentation is wrong or aglSwapBuffers is buggy. And I must say if there is no way to do a propper buffer swap, opengl is worth s#?!t for everything else than utility applications.

Another curiosity:
At “www.xlr8yourmac.com” someone said that with his new iMac came “MacOS 9.0.4 Version 2”, which includes OpenGL v1.1.4 and updated ATI drivers. Apple’s OpenGL page [ “www.apple.com/opengl”] seems to be a little bit outdated, since they are offering v1.1.2. Anyone knows where to get OpenGL v1.1.4???

OK, I just played around a little bit with substituting aglSwapBuffers() with glCopyPixels(). Here are the results:

  • the VBL glitch persists.
  • it’s much slower than aglSwapBuffers().
  • blending gets partially f#?!ed up.
  • seems some colors are missing (reduced to 8bit?). glPixelTransfer was configured properly.

So glCopyPixels() seems not to be usefull for replacing aglSwapBuffers(). But it could be used to draw actually a scene in 320240 and then zooming the scene to 640480 with glPixelZoom(2.0f, 2.0f). This could be a nice hack for RageII boards with only 2mb of video memory or other gfx boards with a slow poly fillrate.