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 HistoryDate | Notes |
---|
2007-09-18 | First Version |
Posted: 2007-09-18
|