Renderer and buffer attributes determine the renderers that the system chooses for your application. Each of the Apple-specific OpenGL APIs provides constants that specify a variety of renderer and buffer attributes. You supply a list of attribute constants to one of the Apple OpenGL functions for choosing a pixel format object. The pixel format object maintains a list of appropriate renderers. In previous chapters, you saw how to set up an attributes array that contains a small set of attributes.
In a real-world application, selecting attributes is an art because you don't know the exact combination of hardware and software that your application will run on. An attribute list that is too restrictive could miss out on future capabilities or not be able to run on many systems. For example, if you specify a buffer of a specific depth, your application won't be able to take advantage of a larger buffer when more memory is available in the future. In this case, you might specify a required minimum and direct OpenGL to use the maximum available.
Although you might want to specify attributes that make your OpenGL content look and run its best, you also need to consider whether you'll allow your application to run on a less-capable system at the expense of speed or detail. If tradeoffs are acceptable, you'll need to set the attributes accordingly.
Buffer Size Attribute Selection Tips
Attributes that are not Recommended
Ensuring that Back Buffer Contents Remain the Same
Ensuring a Valid Pixel Format Object
Ensuring a Specific Type of Renderer
Ensuring a Single Renderer for a Display
See Also
Follow these guidelines to choose buffer attributes that specify buffer size:
To choose color, depth, and accumulation buffers that are greater than or equal to a size you specify, use the minimum policy attribute (NSOpenGLPFAMinimumPolicy
, AGL_MINIMUM_POLICY
, and kCGLPFAMinimumPolicy
).
To choose color, depth, and accumulation buffers that are closest in size to a size you specify, use the closest policy attribute (NSOpenGLPFAClosestPolicy
, AGL_CLOSEST_POLICY
, and kCGLPFAClosestPolicy
).
To choose the largest color, depth, and accumulation buffers available, use the maximum policy attribute (NSOpenGLPFAMaximumPolicy
, AGL_MAXIMUM_POLICY
, and kCGLPFAMaximumPolicy
). As long as you pass a value that is greater than 0
, this attribute specifies the use of color, depth, and accumulation buffers that are the largest size possible.
There are several renderer and buffer attributes that are no longer recommended either because they are too narrowly focused or no longer useful:
The robust attribute (NSOpenGLPFARobust
, AGL_ROBUST
, and kCGLPFARobust
) specifies only those renderers that do not have any failure modes associated with a lack of video card resources.
The multiple-screen attribute (NSOpenGLPFAMultiScreen
, AGL_MULTISCREEN
, and kCGLPFAMultiScreen
) specifies only those renderers that can drive more than one screen at a time.
The multiprocessing-safe attribute (AGL_MP_SAFE
and kCGLPFAMPSafe
) specifies only those renderers that are thread safe. This attribute is deprecated in Mac OS X because all renderers can accept commands for threads running on a second processor. However, this does not mean that all renderers are thread safe or reentrant. See “Multithreading and OpenGL.”
The compliant attribute (NSOpenGLPFACompliant
, AGL_COMPLIANT
, and kCGLPFACompliant
) specifies only OpenGL-compliant renderers. All Mac OS X renderers are OpenGL-compliant, so this attribute is no longer useful.
A backing store attribute (NSOpenGLPFABackingStore
, AGL_BACKING_STORE
, or kCGLPFABackingStore
) is required whenever an application depends on the back buffer contents remaining the same after a swap buffer call.
The pixel format routines (the initWithAttributes
method of the NSOpenGLPixelFormat
class, aglChoosePixelFormat
, and CGLChoosePixelFormat
) return a pixel format object to your application that you use to create a rendering context. The buffer and renderer attributes that you supply to the pixel format routine determine the characteristics of the OpenGL drawing sent to the rendering context. If the system can't find at least one pixel format that satisfies the constraints specified by the attribute array, it returns NULL
for the pixel format object. In this case, your application should have an alternative that ensures it can obtain a valid object.
One alternative is to set up your attribute array with the least restrictive attribute first and the most restrictive attribute last. Then, it is fairly easy to adjust the attribute list and make another request for a pixel format object. The code in Listing 7-1 illustrates this technique using the CGL API, but you can just as easily use Cocoa or the AGL API. Notice that the initial attributes list is set up with the supersample attribute last in the list. If the function CGLChoosePixelFormat
returns NULL
the first time it's called, the code sets the supersample attribute to NULL
and once again requests a pixel format object.
Listing 7-1 Using the CGL API to create a pixel format object
int last_attribute = 6; |
CGLPixelFormatAttribute attribs[] = |
{ |
kCGLPFAAccelerated, |
kCGLPFAColorSize, 24 |
kCGLPFADepthSize, 16, |
kCGLPFADoubleBuffer, |
kCGLPFASupersample, |
0 |
}; |
CGLPixelFormatObj pixelFormatObj; |
long numPixelFormats; |
long value; |
CGLChoosePixelFormat (attribs, &pixelFormatObj, &numPixelFormats); |
if( pixelFormatObj == NULL ) { |
attribs[last_attribute] = NULL; |
CGLChoosePixelFormat (attribs, &pixelFormatObj, &numPixelFormats); |
} |
if( pixelFormatObj == NULL ) { |
// Your code to notify the user and take action. |
} |
There are times when you'll want to ensure that you obtain a pixel format that supports a specific renderer type, such as a hardware-accelerated renderer. Table 7-1 lists attributes that support specific types of renderers. The table reflects the following tips for setting up pixel formats:
To select only hardware-accelerated renderers, use both the accelerated and no recovery attributes.
To use only the floating point software renderer, use the appropriate generic floating-point constant.
To render to system memory, use the offscreen pixel attribute. Note that this rendering option does not use hardware acceleration.
To render offscreen with hardware acceleration, specify a pixel buffer attribute. (See “Rendering to a Pixel Buffer.”)
Renderer type | CGL | AGL | Cocoa |
---|---|---|---|
Hardware-accelerated onscreen | |||
Software (floating-point) | |||
Software (deprecated on Intel-based Macs) | |||
System memory (not accelerated) | |||
Hardware-accelerated offscreen |
In some cases you may want to use a specific hardware renderer and nothing else. Since the OpenGL framework normally provides a software renderer as a fallback in addition to whatever hardware renderer it chooses, you need to prevent OpenGL from choosing the software renderer as an option. You either need to specify the no recovery attribute for a windowed drawable object or use a full-screen drawable object. (The full-screen attribute always implies not to use the software renderer as an option.)
Limiting a context to use a specific display, and thus a single renderer, has its risks. If your application runs on a system that uses more than one display, then dragging a windowed drawable object from one display to the other will likely yield a less than satisfactory result. Either the rendering will fail, or OpenGL uses the specified renderer to copy the drawing to the second display. The same unsatisfactory result happens when attaching a full-screen context to another display. If you choose to use the hardware renderer associated with a specific display, you need to add code that detects and handles display changes.
The three code examples that follow show how to use each of the Apple-specific OpenGL APIs to set up a context that uses a single renderer. Listing 7-2 shows how to set up an NSOpenGLPixelFormat
object that supports a single renderer. The attribute NSOpenGLPFANoRecovery
specifies to OpenGL not to provide the fallback option of the software renderer.
Listing 7-2 Setting an NSOpenGLContext
object to use a specific display
#import <Cocoa/Cocoa.h> |
+ (NSOpenGLPixelFormat*)defaultPixelFormat |
{ |
NSOpenGLPixelFormatAttribute attributes [] = { |
NSOpenGLPFAScreenMask, 0, |
NSOpenGLPFANoRecovery, |
NSOpenGLPFADoubleBuffer, |
(NSOpenGLPixelFormatAttribute)nil }; |
CGDirectDisplayID display = CGMainDisplayID (); |
// Adds the display mask attrib for selected display |
attributes[1] = (NSOpenGLPixelFormatAttribute) |
CGDisplayIDToOpenGLDisplayMask (display); |
return [[(NSOpenGLPixelFormat *)[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] |
autorelease]; |
} |
Listing 7-3 shows how to use AGL to set up a context that uses a single renderer. The attribute AGL_NO_RECOVERY
specifies to OpenGL not to provide the fallback option of the software renderer.
Listing 7-3 Setting an AGL context to use a specific display
#include <AGL/agl.h> |
GLint attrib[] = {AGL_RGBA, AGL_DOUBLEBUFFER, AGL_NO_RECOVERY, AGL_NONE}; |
GDHandle display = GetMainDevice (); |
AGLPixelFormat aglPixFmt = aglChoosePixelFormat (&display, 1, attrib); |
Listing 7-4 shows how to use CGL to set up a context that uses a single renderer. The attribute kCGLPFAFullScreen
ensures that OpenGL does not provide the fallback option of the software renderer.
Listing 7-4 Setting a CGL context to use a specific display
#include <OpenGL/OpenGL.h> |
CGLPixelFormatAttribute attribs[] = { kCGLPFADisplayMask, 0, |
kCGLPFAFullScreen, |
kCGLPFADoubleBuffer, |
0 }; |
CGLPixelFormatObj pixelFormat = NULL; |
long numPixelFormats = 0; |
CGLContextObj cglContext = NULL; |
CGDirectDisplayID display = CGMainDisplayID (); |
// Adds the display mask attrib for selected display |
attribs[1] = CGDisplayIDToOpenGLDisplayMask (display); |
CGLChoosePixelFormat (attribs, &pixelFormat, &numPixelFormats); |
Reference documentation for buffer and renderer attributes in the Constants sections of:
© 2004, 2008 Apple Inc. All Rights Reserved. (Last updated: 2008-06-09)