2015-10-05 32 views
0

我有一個OpenGL應用程序,我在2011年MacBookPro上運行Xcode 7.0.1。操作系統中的NSView 10.11埃爾卡皮坦拋出錯誤

我最近從OS 10.10提升至10.11埃爾卡皮坦,現在用NSViews窗口拋出這個錯誤(部署目標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,以及金屬,需要2012或更高版本。我沒有使用Metal,但我仍然認爲這可能是一個因素。

計算機復古是產生錯誤的問題,還是有一些其他語法我應該用來獲取圖形上下文?

我不知道爲什麼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 

這是什麼這個特殊的窗口看起來像一個形象:

enter image description here

的行爲是不相符的。例如,這個狀態窗口應該出現在計算過程中的幾個步驟中的每一個,但是看起來只有每隔一個窗口被顯示(例如步驟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> 

的的.xib文件看起來是這樣的:

enter image description here

有一個自定義進度指示器在這個窗口中(由兩個白色方塊界定),這是不可見的,但它在那裏。

樣本代碼,以顯示該窗口看起來像:

[self showStatusWindowWithString1:@"Calculation Complete" String2:timeMessage ButtonOn:YES AbortOn:NO ProgressOn:NO ProgressMax:100.0 Title:@"Fractal Run Time"]; 

和用於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; 
} 

肯Thomases診斷出回溯表示,正在產生的無效的上下文錯誤在[StatusWindowController updateStatusProgress:](這會更新自定義進度指示器)。

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

要:

我從改變了這種方法

- (void) updateStatusProgress:(double)statusprogress 
{ 
    [statusProgressIndicator setDoubleValue:statusprogress]; 
    [statusProgressIndicator setNeedsDisplay:YES]; 
} 

它看起來對我來說,是被在多個地方產生的錯誤消息,但這一變化停止了所有的錯誤消息。

我的下一個問題是,狀態窗口(上圖)不是每次都顯示,有時只顯示。再次,這一切都在Yosemite,Xcode 6.4中運行良好。

我現在發現,當狀態窗口不顯示,我可以通過模態運行它來顯示。奇怪。

我正在處理的最後一個問題是GLSL着色器沒有按照他們應該寫入到OpenGL視圖。我已經通過在片段着色器末尾添加一行來測試着色器是否正在加載和運行:fragColor = vec4(1.0,0.0,0.0,1.0);它將視圖完全變紅,因爲它應該。

片段着色器實際上應該是從紋理採樣,所以我加載了全部紋理(255,0,0,255)來通過在片段着色器末尾放置一個簡單的採樣語句來測試採樣:

fragColor = texture(Texture, texCoord).rgba; 

但沒有任何東西被寫入,因此將紋理加載到着色器中一定會有問題。我現在正在處理這個問題。

+0

如果視圖是OpenGL視圖,那麼您使用'CGContext'作爲什麼?你有沒有試過按照建議設置'CG_CONTEXT_SHOW_BACKTRACE'環境變量,如果是這樣,什麼是回溯? –

+0

@Ken Thomases我添加了更多細節,包括樣本回溯。瀏覽Apple論壇後,我認爲這可能實際上是一個Xcode 7問題。 – jwlaughton

+0

回溯表示問題出在您未顯示的方法' - [StatusWindowController updateStatusProgress:]'中。顯示。另外,你的觀點是否有層次支持? –

回答

0

導致「無效上下文0x0」消息的問題是您直接呼叫-drawRect:。這從來沒有效。框架調用-drawRect:後,它已經建立了適當的圖形上下文和諸如座標變換之類的東西,將圖形放在窗口的正確位置並剪切到視圖的邊界。如果你在其他時間稱呼它,那麼就沒有建立任何環境,沒有任何好的結果。

如果您必須立即重繪,則可以調用-display...方法之一。

但是,通常情況下最好按照您現在所做的完成:只需將視圖標記爲需要顯示,並讓Cocoa在適當的時候重新繪製它。

您應該針對其他問題發佈單獨的問題。

+0

我環視了一下我的代碼,發現這是我直接調用drawRect的唯一地方。我通常使用顯示方法。謝謝你的幫助。 – jwlaughton

0

我剛剛做了一個應用程序的快速構建,這些應用程序之前沒有在EC之前重建。它一切正常。

也許你可以發表更多的細節。代碼和崩潰點?

+0

約翰,謝謝你的迴應。在環顧蘋果論壇時,看起來這可能實際上是Xcode 7問題,而不是EC。 – jwlaughton

+0

我的應用程序也很好,沒有任何警告或錯誤,並且不會「崩潰」(沒有SIGABRT或BAD_ACCESS)。它只是不正確運行併產生錯誤。 – jwlaughton

相關問題