我有一個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
這是什麼這個特殊的窗口看起來像一個形象:
的行爲是不相符的。例如,這個狀態窗口應該出現在計算過程中的幾個步驟中的每一個,但是看起來只有每隔一個窗口被顯示(例如步驟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文件看起來是這樣的:
有一個自定義進度指示器在這個窗口中(由兩個白色方塊界定),這是不可見的,但它在那裏。
樣本代碼,以顯示該窗口看起來像:
[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;
但沒有任何東西被寫入,因此將紋理加載到着色器中一定會有問題。我現在正在處理這個問題。
如果視圖是OpenGL視圖,那麼您使用'CGContext'作爲什麼?你有沒有試過按照建議設置'CG_CONTEXT_SHOW_BACKTRACE'環境變量,如果是這樣,什麼是回溯? –
@Ken Thomases我添加了更多細節,包括樣本回溯。瀏覽Apple論壇後,我認爲這可能實際上是一個Xcode 7問題。 – jwlaughton
回溯表示問題出在您未顯示的方法' - [StatusWindowController updateStatusProgress:]'中。顯示。另外,你的觀點是否有層次支持? –