Q: I'm working with QTCoreVideo101 but it never returns a VisualContextRef. Calling QTOpenGLTextureContextCreate always fails with error -9459. I have a Mac Pro system with a third party video card for Final Cut Pro. How can I create a QuickTime OpenGL Texture Visual Context?A: The most likely reason for the -9459 (kQTVisualContextNotAllowedErr) error is the third party video card. If the card presents itself as a video device but does not support accelerated surfaces QTOpenGLTextureContextCreate will fail. Note: In Quartz, the term display refers to a graphics hardware system consisting of a framebuffer, a color correction (gamma) table or color palette, and possibly an attached monitor. To successfully create a QuickTime OpenGL Texture Visual Context, the non-accelerated display(s) may be masked out by creating a display mask (simply a bitmask used to specify a set of attached displays) that only identifies the displays supporting accelerated surfaces. This can be done using Quartz Display Services APIs such as CGDisplayUsesOpenGLAcceleration and CGDisplayIDToOpenGLDisplayMask. This display mask (with the non-accelerated display(s) masked out) is then used when creating the OpenGL Pixel Format object. This Pixel Format object is used when creating the OpenGL Context and when calling QTOpenGLTextureContextCreate. Listing 1 demonstrates how to build the display mask, while listing 2 demonstrates how to use the returned display mask when creating the NSOpenGLPixelFormat object. Listing 1: Return the Accelerated Display Mask.
static CGOpenGLDisplayMask GetTheAcceleratedDisplayMask(void)
{
const CGDisplayCount maxDisplays = sizeof(CGOpenGLDisplayMask) * 8; // the number of displays
CGDirectDisplayID displays[maxDisplays]; // represents the unique identifier for an attached display
CGDisplayCount display, displayCount;
CGOpenGLDisplayMask displayMask = 0; // bitmask used in OpenGL to specify a set of attached displays
// get the list of displays that are active (or drawable)
if (CGGetActiveDisplayList(maxDisplays, displays, &displayCount) == kCGErrorSuccess) {
// does the display support acceleration
for (display = 0; display < displayCount; display++) {
if (CGDisplayUsesOpenGLAcceleration(displays[display])) {
// it does, so get the OpenGL display mask for the display and update our display mask
displayMask |= CGDisplayIDToOpenGLDisplayMask(displays[display]);
}
}
}
// return our display mask that now has all the non-accelerated displays filtered out
return displayMask;
}
Note: CGGetActiveDisplayList vs. CGGetOnlineDisplayList In listing 1, we need the active display list. An active display is connected, awake and available for drawing, while a display is considered online simply when the frame buffer is connected to a monitor. In a hardware mirroring set, only the primary display is active. Listing 2: Using the Display Mask by Subclassing NSOpenGLView
@interface MyOpenGLView : NSOpenGLView
{
...
QTVisualContextRef mQTOpenGLTextureVisualContext;
}
...
- (QTVisualContextRef)visualContext;
- (void) setVisualContextRef:(QTVisualContextRef)inVisualContext;
...
@end
@implementation MyOpenGLView
+ (NSOpenGLPixelFormat *)defaultPixelFormat
{
// create an NSOpenGLPixelFormat object with the appropriate display mask
CGOpenGLDisplayMask myDisplayMask = GetTheAcceleratedDisplayMask();
if (0 != myDisplayMask) {
NSOpenGLPixelFormatAttribute attributes[] =
{
NSOpenGLPFADoubleBuffer, // double buffered pixel format
NSOpenGLPFAAccelerated, // hardware accelerated renderer
NSOpenGLPFANoRecovery, // disable all failure recovery systems
//** bit mask of supported physical screens **//
NSOpenGLPFAScreenMask, (NSOpenGLPixelFormatAttribute)myDisplayMask,
(NSOpenGLPixelFormatAttribute)0
};
return [[(NSOpenGLPixelFormat*)[NSOpenGLPixelFormat alloc]
initWithAttributes:attributes] autorelease];
} else {
return [super defaultPixelFormat];
}
}
- (id)initWithFrame:(NSRect)frameRect
{
return [super initWithFrame:frameRect pixelFormat:[MyOpenGLView defaultPixelFormat]];
}
- (void)prepareOpenGL
{
...
if (nil != [self openGLContext]) {
long swapInterval = 1;
// sync with screen refresh to avoid tearing
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
}
...
// create the QuickTime Texture Visual Context for rendering to my custom NSOpenGLView
if (NULL == [self visualContextRef]) {
QTVisualContextRef aQTOpenGLTextureContext;
OSStatus status = QTOpenGLTextureContextCreate(kCFAllocatorDefault,
[[self openGLContext] CGLContextObj],
(CGLPixelFormatObj)[[self pixelFormat] CGLPixelFormatObj],
NULL, &aQTOpenGLTextureContext);
if (noErr == status) {
[self setVisualContextRef:aQTOpenGLTextureContext];
...
} else {
[self setVisualContextRef:NULL];
}
}
...
}
...
- (QTVisualContextRef)visualContext
{
return mQTOpenGLTextureVisualContext;
}
- (void)setVisualContextRef:(QTVisualContextRef)inVisualContext
{
mQTOpenGLTextureVisualContext = inVisualContext;
}
...
ReferencesBack to Top  Document Revision History| Date | Notes |
|---|
| 2007-09-18 | First Version |
Posted: 2007-09-18
|