QuickTime Texture Visual Context - kQTVisualContextNotAllowedErr with non-accelerated graphics cards
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: 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?
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.
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; } |
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; } ... |
References
Document Revision History
Date | Notes |
---|---|
2007-09-18 | New document that discusses how to create a display mask and avoid a kQTVisualContextNotAllowedErr when using a non-accelerated graphics card. |
Copyright © 2007 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2007-09-18