Synchronizing OpenGL rendering updates to the vertical refresh of the display

Q: How do I avoid tearing in OpenGL?

A: Tearing is a visual artifact that occurs when the display begins reading from a buffer before your application's rendering to that buffer has completed.

You can use the swap interval context parameter to avoid tearing. This parameter is zero by default. If you set it to a non-zero value, OpenGL will synchronize buffer swaps with a vertical retrace event.

One potential reason to have a zero swap interval is to measure the maximum possible number of frames that can be rendered within a given time. This is because setting swap interval to a non-zero value caps the effective frame rate of your application to an integer divisor of the display's refresh rate. For instance, if your application can complete its rendering within one display refresh period, the frame rate will be capped at the refresh rate. If, however, your application takes longer than one refresh period, then the buffer swap will have to wait until the next refresh event. This effectively drops your frame rate to 1 / [time to render a frame rounded up to nearest vertical retrace period].

Note: Although LCD displays don't have a vertical blanking period as such; they have a fixed refresh frequency of around 60Hz.

NSOpenGLContexts

Listing 1 shows how to enable and disable synchronization in an NSOpenGLContext.

Listing 1: Synchronizing buffer swaps to VBL in an NSOpenGLView.

long swapInterval = 1; // request synchronization
//long swapInterval = 0; // disable synchronization

[[self openGLContext] setValues:&swapInterval forParameter: NSOpenGLCPSwapInterval];

Back to Top 

AGL Contexts

Listing 2 shows how to enable and disable synchronization using the AGL API.

Listing 2: Synchronizing buffer swaps to VBL in the current AGL Context.

long swapInterval = 1;   // request synchronization
//long swapInterval =0;  // disable synchronization

AGLContext ctx = aglGetCurrentContext();
if (NULL != ctx) aglSetInteger(ctx, AGL_SWAP_INTERVAL, &swapInterval);

Back to Top 

CGL Contexts

Listing 3 shows how to enable and disable synchronization using the CGL API.

Listing 3: Synchronizing buffer swaps to VBL in the current CGL Context

long swapInterval = 1; // request synchronization
//long swapInterval = 0; // disable synchronization

CGLContextObj ctx = CGLGetCurrentContext();
if (NULL != ctx) CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);

Note: You can use CGLSetParameter to set the swap interval for AGLContext and NSOpenGLContext objects because each of these contexts are built on the CGLContextObj opaque type.

Back to Top 

GLUT Defaults

GLUT based programs have the additional convenience of a default setting. The default setting is only evaluated during application launch, so for the change to take effect the application must be restarted.

GLUT defaults can be accessed on their application menus:

Figure 1: Accessing the preferences of a GLUT application

Figure 1, Accessing the preferences of a GLUT application

To enable synchronization to VBL by default select "Default Synchronize to Vertical Blank" and restart the application.

Figure 2: Selecting synchronization default.

Figure 2, Selecting synchronization default.

Back to Top 

References

The OpenGL Programming Guide for Mac OS X has a section about this topic under the best practices area of improving performance.

Back to Top 

Document Revision History

DateNotes
2007-07-16First Version

Posted: 2007-07-16


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.