Opengl OS 10.11中的NSView El Capitan抛出错误

Opengl OS 10.11中的NSView El Capitan抛出错误,opengl,nsview,osx-elcapitan,Opengl,Nsview,Osx Elcapitan,我有一个OpenGL应用程序,我在2011 MacBookPro的Xcode 7.0.1中运行 我最近从OS 10.10升级到10.11 El Capitan,现在带NSView的windows将抛出以下错误部署目标10.11、10.10或10.9: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable. 在N

我有一个OpenGL应用程序,我在2011 MacBookPro的Xcode 7.0.1中运行

我最近从OS 10.10升级到10.11 El Capitan,现在带NSView的windows将抛出以下错误部署目标10.11、10.10或10.9:

invalid context 0x0. If you want to see the backtrace, please set     
CG_CONTEXT_SHOW_BACKTRACE environmental variable.
在NSView drawRect方法中,我使用以下语句获得CGContext:

CGContextRef context = [[NSGraphicsContext currentContext] CGContext];
此外,我的GLSL 4.1着色器不再向OpenGL窗口写入任何内容

在我升级到El Capitan之前,这段代码没有给我任何问题,几乎完全相同的代码在2012 MacBookPro、OS 10.10、Xcode 6.4、部署目标10.9或10.10上运行良好,没有错误。唯一的代码区别是NSView drawRect方法中的图形上下文是通过以下方式获得的:

CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
我想我的问题可能是有问题的电脑是2011年的MacBookPro,而Metal需要2012年或更高版本。我没有使用金属,但我仍然认为这可能是一个因素

计算机是产生错误的问题,还是我应该使用其他语法来获取图形上下文

我不知道为什么GLSL着色器不再工作。有什么想法吗

应用程序主窗口是OpenGL视图,但我在弹出式用户界面窗口、自定义按钮和各种其他用途中使用了许多NSView。下面是其中一个最简单窗口的完整代码。同样,在我升级到EC和Xcode 7.0.1之前,这一切都运行良好

@implementation StatusView

// **************************** Init **********************************

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {

    }
    return self;
}

// ************************** Draw Rect ********************************

- (void)drawRect:(NSRect)dirtyRect
{
    if(windowManager)
    {
        CGContextRef context = [[NSGraphicsContext currentContext] CGContext];

        // Define a color space variable
        CGColorSpaceRef rgbColorspace = CGColorSpaceCreateDeviceRGB();            

        // Get the bounds
        NSRect nsBounds = [self bounds];

        // Set the graphics bounds
        CGRect cgBounds = NSRectToCGRect(nsBounds);                               

        // ****** Draw the Background in Transparent Black

        CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
        CGContextFillRect(context, cgBounds);

        // Set the text matrix.
        CGContextSetTextMatrix(context, CGAffineTransformIdentity);

        // Create a color that will be added as an attribute to the attrString for normal text.
        CGFloat textColorComponents[] = { 1.0, 1.0, 1.0, 1.0 };
        CGColorRef whiteColor = CGColorCreate(rgbColorspace, textColorComponents);

        // Create a color that will be added as an attribute to the attrString for invisible text.
        CGFloat invisibleTextColorComponents[] = { 0.0, 0.0, 0.0, 0.0 };
        CGColorRef invisibleColor = CGColorCreate(rgbColorspace, invisibleTextColorComponents);

        // Create a font for normal text.
        CFStringRef stringFontName = CFSTR("AppleCasual");
        CTFontRef stringFont = CTFontCreateWithName(stringFontName, 18.0, NULL);

        CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
        CGContextFillRect(context, cgBounds);

        // ************* Box the Window in Gray ***************************

        CGContextMoveToPoint(context, 0.0,1.0);
        CGContextAddLineToPoint(context,0.0, cgBounds.size.height - 1.0);
        CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, cgBounds.size.height - 1.0);
        CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, 1.0);
        CGContextAddLineToPoint(context,0.0, 1.0);
        CGContextSetLineWidth(context, 2.0);
        CGContextSetRGBStrokeColor(context, 0.7, 0.7, 0.7, 1.0);
        CGContextStrokePath(context);

        // *********** Draw String1

        CGPoint endingTextPoint;

        if(windowManager->statusTextBox1String)
        {
            // Create a mutable attributed string with a max length of 0 for normal text.
            CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);

            // Create a path which will bound the area where you will be drawing text.
            CGMutablePathRef invisibleTextPath = CGPathCreateMutable();

            // Create a path which will bound the area where you will be drawing text.
            CGMutablePathRef string1TextPath = CGPathCreateMutable();

            // Initialize a string.
            CFStringRef textString = (__bridge CFStringRef)windowManager->statusTextBox1String;
            CFIndex textStringLength = CFStringGetLength (textString);

            // Measure the string length
            CGRect invisibleTextBounds = CGRectMake(0.0, 0.0, cgBounds.size.width, 30.0);
            CGPathAddRect(invisibleTextPath, NULL, invisibleTextBounds);

            // Copy the textString into attrString
            CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), textString);

            // Set the color and font.
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, invisibleColor);
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);

            // Create the framesetter with the attributed string.
            CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);

            CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), invisibleTextPath, NULL);

            // Draw the specified frame in the given context.
            CTFrameDraw(frame, context);

            endingTextPoint = CGContextGetTextPosition(context);

            // Draw the Text

            // Set a rectangular path.
            CGRect textBounds = CGRectMake((cgBounds.size.width / 2.0) - (endingTextPoint.x / 2.0), 140.0, cgBounds.size.width, 30.0);
            CGPathAddRect(string1TextPath, NULL, textBounds);

            // Copy the textString into attrString
            CFAttributedStringReplaceString (attrString, CFRangeMake(0, textStringLength), textString);

            // Set the color and fontof the first chars.
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, whiteColor);
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);

            // Create the framesetter with the attributed string.
        framesetter = CTFramesetterCreateWithAttributedString(attrString);

            // Create a frame.
            frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), string1TextPath, NULL);

            // Draw the specified frame in the given context.
            CTFrameDraw(frame, context);

            CFRelease(string1TextPath);
            CFRelease(invisibleTextPath);
            CFRelease(frame);
            CFRelease(framesetter);
            CFRelease(attrString);
        }

        // ****************** Draw String 2

        if(windowManager->statusTextBox2String)
        {
            CGContextSetRGBFillColor(context, 0.0f, 0.0f, 0.0f, 0.0f);
            CGContextFillRect(context, cgBounds);

            // ********** Box the Window in Gray ***********************

            CGContextMoveToPoint(context, 0.0,1.0);
            CGContextAddLineToPoint(context,0.0, cgBounds.size.height - 1.0);
            CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, cgBounds.size.height - 1.0);
            CGContextAddLineToPoint(context,cgBounds.size.width - 2.0, 1.0);
            CGContextAddLineToPoint(context,0.0, 1.0);
            CGContextSetLineWidth(context, 2.0);
            CGContextSetRGBStrokeColor(context, 0.7, 0.7, 0.7, 1.0);
            CGContextStrokePath(context);

            // Create a mutable attributed string with a max length of 0 for normal text.
            CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);

            // Create a path which will bound the area where you will be drawing text.
            CGMutablePathRef invisibleTextPath = CGPathCreateMutable();

            // Create a path which will bound the area where you will be drawing text.
            CGMutablePathRef string2TextPath = CGPathCreateMutable();

            // Initialize a string.
            CFStringRef textString = (__bridge CFStringRef)windowManager->statusTextBox2String;
            CFIndex textStringLength = CFStringGetLength (textString);

            // Measure the string length
            CGRect invisibleTextBounds = CGRectMake(0.0, 0.0, cgBounds.size.width, 130.0);
            CGPathAddRect(invisibleTextPath, NULL, invisibleTextBounds);

            // Copy the textString into attrString
            CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), textString);

            // Set the color and font
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, invisibleColor);
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);

            // Create the framesetter with the attributed string.
            CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);

            CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), invisibleTextPath, NULL);

            // Draw the specified frame in the given context.
            CTFrameDraw(frame, context);

            endingTextPoint = CGContextGetTextPosition(context);

            // Draw the Text

            // Set a rectangular path.
            CGRect textBounds = CGRectMake((cgBounds.size.width / 2.0) - (endingTextPoint.x / 2.0), 100.0, cgBounds.size.width, 30.0);
            CGPathAddRect(string2TextPath, NULL, textBounds);

            // Copy the textString into attrString
            CFAttributedStringReplaceString (attrString, CFRangeMake(0, textStringLength), textString);

            // Set the color and fontof the first chars.
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTForegroundColorAttributeName, whiteColor);
            CFAttributedStringSetAttribute(attrString, CFRangeMake(0, textStringLength), kCTFontAttributeName, stringFont);

            // Create the framesetter with the attributed string.
            framesetter = CTFramesetterCreateWithAttributedString(attrString);

            // Create a frame.
            frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), string2TextPath, NULL);

            // Draw the specified frame in the given context.
            CTFrameDraw(frame, context);

            CFRelease(string2TextPath);
            CFRelease(invisibleTextPath);
            CFRelease(frame);
            CFRelease(framesetter);
            CFRelease(attrString);
        }

        CFRelease(stringFont);
        CFRelease(whiteColor);
        CFRelease(invisibleColor);

        CGContextFlush(context);
    }

    return;
}

@end
这是此特定窗口的图像:

    [self showStatusWindowWithString1:@"Calculation Complete" String2:timeMessage ButtonOn:YES AbortOn:NO ProgressOn:NO ProgressMax:100.0 Title:@"Fractal Run Time"];
这种行为并不一致。例如,对于计算过程中的每个步骤,都应显示此状态窗口,但它看起来只显示其他窗口,例如步骤2、4和6,而不是步骤1、3或5

生成了许多错误,但这是其中一个错误的回溯示例:

Oct  9 10:23:30  WispFractals3D[746] <Error>: CGContextRestoreGState: invalid context 0x0. Backtrace:
  <-[StatusWindowController updateStatusProgress:]+228>
   <-[AppController updateStatusProgress:]+64>
    <-[AppController runTheFractal:]+804>
     <_os_activity_initiate+75>
      <-[NSApplication sendAction:to:from:]+460>
       <-[NSMenuItem _corePerformAction]+336>
        <-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:]+114>
         <_os_activity_initiate+75>
          <-[NSMenu performActionForItemAtIndex:]+131>
           <-[NSMenu _internalPerformActionForItemAtIndex:]+35>
            <-[NSCarbonMenuImpl       _carbonCommandProcessEvent:handlerCallRef:]+107>
             <NSSLMMenuEventHandler+708>
              <_ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec+1231>
               <_ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec+404>
                <SendEventToEventTarget+40>
                 <_ZL18SendHICommandEventjPK9HICommandjjhPKvP20OpaqueEventTargetRefS5_PP14OpaqueEventRef+411>
                  <SendMenuCommandWithContextAndModifiers+59>
                   <SendMenuItemSelectedEvent+188>
                    <_ZL19FinishMenuSelectionP13SelectionDataP10MenuResultS2_+96>
                     <_ZL14MenuSelectCoreP8MenuData5PointdjPP13OpaqueMenuRefPt+711>
                      <_HandleMenuSelection2+460>
                       <_NSHandleCarbonMenuEvent+277>
                        <_DPSNextEvent+1906>
                         <-[NSApplication _nextEventMatchingEventMask:untilDate:inMode:dequeue:]+454>
                          <-[NSApplication run]+682>
                           <NSApplicationMain+1176>
                            <main+34>
showStatusWindow方法的代码为:

- (void)showStatusWindowWithString1:(NSString *)string1 String2:(NSString *)string2 ButtonOn:(BOOL)buttonon AbortOn:(BOOL)aborton ProgressOn:(BOOL)progresson ProgressMax:(double)progressmax Title:(NSString *)title
{
    statusWindowTitle = title;
    statusTextBox1String = string1;
    statusTextBox2String = string2;
    statusButtonOn = buttonon;
    abortOn = aborton;
    statusProgressOn = progresson;
    statusProgressMax = progressmax;

    if (!statusWindowController)
    {
        statusWindowController = [[StatusWindowController alloc] initWithWindowNibName:@"StatusWindow" Manager:self];
    }

    [[statusWindowController window] setTitle:statusWindowTitle];

    [statusWindowController showWindow:self];
    [fileStatusWindow makeKeyAndOrderFront:self];

    appDelegate->fileStatusWindowOpenFlag = YES;
    [appDelegate checkFlags];

    return;
}
Ken Thomases诊断回溯表明[StatusWindowController updateStatusProgress:]中生成了无效的上下文错误。这将更新自定义进度指示器

我将此方法更改为:

- (void) updateStatusProgress:(double)statusprogress
{
    [statusProgressIndicator setDoubleValue:statusprogress];
    [statusProgressIndicator drawRect:[statusProgressIndicator bounds]];
}
致:

在我看来,错误消息似乎是在多个地方生成的,但这一更改停止了所有错误消息

我的下一个问题是,上面的状态窗口图像并不是每次都显示,只是有时候。同样,这一切在约塞米蒂Xcode 6.4中运行良好

我现在发现,当状态窗口不显示时,我可以通过模式运行它来显示它。奇怪

我正在处理的最后一个问题是GLSL着色器没有像它们应该的那样写入OpenGL视图。我已经通过在片段着色器的末尾添加一行来测试着色器是否正在加载和运行:fragColor=vec41.0,0.0,0.0,1.0;,这使景色完全变成了红色

片段着色器实际上应该从纹理中采样,因此我将所有255、0、0、255加载到该纹理中,通过在片段着色器的末尾放置一个简单的采样语句来测试采样:

fragColor = texture(Texture, texCoord).rgba;

但是没有写入任何内容,因此将纹理加载到着色器中时一定存在问题。我现在正在做这件事。

我刚刚快速构建了一个应用程序,以前没有在电子商务下重建过。一切都很顺利


也许你可以发布更多的细节。代码和崩溃点?

导致无效上下文0x0消息的问题是您直接调用了-drawRect:。这从来都不是有效的-drawRect:在框架设置了适当的图形上下文和坐标变换等内容,以将图形放置在窗口中的正确位置并剪切到视图边界后,框架将调用该函数。如果您在其他时间调用它,那么就没有设置上下文,也不会产生任何好处

如果必须立即重画,可以调用-display。。。方法

但是,通常最好像现在这样做:只需将视图标记为需要显示,并让Cocoa在适当的时候重新绘制


您可能应该针对其他问题发布单独的问题。

如果视图是OpenGL视图,您使用CGContext的目的是什么?您是否尝试过按照建议设置CG_CONTEXT_SHOW_BACKTRACE环境变量,如果是,回溯是什么?@Ken Thomases我添加了更多详细信息,包括回溯示例。在浏览了苹果论坛之后,我认为这实际上可能是一个Xcode 7问题。回溯说问题出在方法-[StatusWindowController updateStatusProgress:]中,您还没有显示该方法。显示出来。另外,您的视图层是否有备份?@Ken Thomases在[StatusWindowController updateStatusProgress]中更改一行代码似乎打破了日志阻塞。我还没有完全解决我所有的问题,但我已经走得够远了,我相信我能从这里到达那里。请张贴一个我可以接受的答案。
我很高兴你解决了部分问题,但是没有看到你的-updateStatusProgress:method和what change fixed things,我不知道我的答案是什么。John,谢谢你的回答。环顾苹果论坛,看起来这实际上可能是Xcode 7问题,而不是EC问题。我的应用程序也可以正常运行,没有警告或错误,并且不会崩溃,没有SIGABRT或BAD_访问。它不能正确运行并产生错误。我查看了一下我的代码,发现这是我唯一直接调用drawRect的地方。我通常使用显示方法。谢谢你的帮助。
fragColor = texture(Texture, texCoord).rgba;