分类: LINUX
2012-03-31 15:47:22
Vsync prevents your program's frame rate from exceeding the refresh rate your graphics hardware is set at, Thus if your graphics card only sends 60 frames to your monitor every second, your program will not render more frames than 60.
As I understand it, Vsync works by forcing OpenGL to wait for the video hardware to set a flag which indicates that it has drawn a frame, before it can swap the image in the back buffer (where it is drawn) to the front buffer (where the image displayed on the monitor is read from).
Reasons for using Vsync:
On windows enabling vsync is straight forward.
Just calling "wglSwapIntervalEXT(1)" has always worked for me.
For some reason I always seem to run into trouble enabling vsync for Linux code.
nVidia and ATI/AMD drivers support the GLX_SGI_swap_control extension which provides the glXSwapIntervalSGI() function.
Strangely the MESA drivers have their own function to control Vsync, and glXSwapIntervalSGI will not work on systems using MESA drivers.
glXSwapIntervalSGI(1); works perfectly with my nVidia graphics card (and nVidia drivers), but my laptop has an Intel graphics card and although glXSwapIntervalSGI compiles and runs, it doesn't do anything.
So I need a way to choose the glXSwapIntervalMESA when its needed and glXSwapIntervalSGI otherwise. My theory is that glXSwapIntervalMESA will only be available on MESA implementations.
I use GLee () to handle OpenGL extensions, unfortunatly it does not seem to define glXSwapIntervalMESA.
As when I try to compile with glXSwapIntervalMESA I get:
undefined reference to `glXSwapIntervalMESA'
It seems that glXSwapIntervalMESA is related to the extension string GLX_MESA_SWAP_CONTROL
printf("extensions: %s \n", glGetString(GL_EXTENSIONS));
does not contain GLX_MESA_SWAP_CONTROL,
but
printf("glXQueryExtensionsString: %s \n", glXQueryExtensionsString(dpy, screen));
does.
A valid rendering context must be available before glXQueryExtensionsString will work.
glXGetProcAddress returns a function pointer to the extension which you pass it.
I was getting confused as:
glXGetProcAddress((const GLubyte*) "GLX_MESA_SWAP_CONTROL");
returns null.
But it should have been:
glXGetProcAddress((const GLubyte*) "glXSwapIntervalMESA");
Which returns the expected not null pointer.
I declare a function pointer:
void (*swapInterval)(int);
This was a guess as I know glXSwapIntervalSGI takes an integer as an argument.
The function pointer is set by this line of code:
swapInterval = (void (*)(int)) glXGetProcAddress((const GLubyte*) "glXSwapIntervalMESA");
Call:
swapInterval(1);
Finally frame rate is limited to 60!!!
I originally used strstr to parse the list of glx extensions, until I came across the page at:
Which argues that strstr is not always reliable because it could return false positives, for example when searching for "GL_EXT_texture" extension, if "GL_EXT_texture3D" is available the strstr method will return true, even if "GL_EXT_texture" can not be found.
This function is slightly modified from the above mentioned webpage:
This function is case sensitive, I needed to pass "GLX_MESA_swap_control".
Now I can do: