Updated Mac OpenGL context handling to be slightly more similar to recommended best practice. Doesn't actually _follow_ best practice because best practice only works in Snow Leopard. Also, avoid unnecessary graphics reset during startup.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3611 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2010-06-26 13:18:31 +00:00
parent 7613a150bf
commit c54fe64bbf
8 changed files with 215 additions and 151 deletions

View File

@ -1282,4 +1282,8 @@
"espeak-default-voice" = "default";
"speech-synthesis-incoming-message" = "Incoming message.";
// Mac multi-screen handling
"oolite-mac-bad-display" = "The display configuration has changed in a way that may impact Oolites performance.";
"oolite-mac-bad-display-2" = "Oolites main window is now on a screen which is not connected to a graphics processor compatible with Oolite. Oolite should continue to work, but performance may be degraded.";
}

View File

@ -108,6 +108,9 @@ extern int debug;
GLfloat display_z;
GLfloat x_offset, y_offset;
int _virtualScreen;
NSData *_pixelFormatAttributes;
JoystickHandler *stickHandler;
}
@ -129,6 +132,8 @@ extern int debug;
- (void) initialiseGLWithSize:(NSSize) v_size;
- (NSData *)pixelFormatAttributes;
- (void) drawRect:(NSRect)rect;
- (void) updateScreen;

View File

@ -33,6 +33,7 @@ MA 02110-1301, USA.
#import <Carbon/Carbon.h>
#import "JoystickHandler.h"
#import "NSFileManagerOOExtensions.h"
#import "OOGraphicsResetManager.h"
#ifndef NDEBUG
#import <Foundation/NSDebug.h>
@ -66,7 +67,8 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
// Pixel Format Attributes for the View-based (non-FullScreen) NSOpenGLContext
NSOpenGLPixelFormatAttribute attrs[] =
{
// // Specify that we want a windowed OpenGL context.
// Specify that we want a windowed OpenGL context.
// Must be first or we'll hit an assert in -[GameController goFullscreen:].
NSOpenGLPFAWindow,
// We may be on a multi-display system (and each screen may be driven by a different renderer), so we need to specify which screen we want to take over.
@ -94,6 +96,8 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
0
};
_pixelFormatAttributes = [[NSData alloc] initWithBytes:attrs length:sizeof attrs];
// Create our non-FullScreen pixel format.
NSOpenGLPixelFormat* pixelFormat = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attrs] autorelease];
@ -107,14 +111,17 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
timeIntervalAtLastClick = [NSDate timeIntervalSinceReferenceDate];
_virtualScreen = [[self openGLContext] currentVirtualScreen];
return self;
}
- (void) dealloc
{
if (typedString)
[typedString release];
DESTROY(typedString);
DESTROY(_pixelFormatAttributes);
[super dealloc];
}
@ -222,6 +229,48 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
}
- (void) noteMovedToBadDisplay
{
NSRunInformationalAlertPanel(DESC(@"oolite-mac-bad-display"), @"%@", nil, nil, nil, DESC(@"oolite-mac-bad-display-2"));
}
- (void) update
{
NSOpenGLContext *context = [self openGLContext];
[context update];
int virtualScreen = [context currentVirtualScreen];
if (virtualScreen != _virtualScreen)
{
@try
{
[[OOGraphicsResetManager sharedManager] resetGraphicsState];
_virtualScreen = virtualScreen;
}
@catch (NSException *exception)
{
/* Graphics reset failed, most likely because of OpenGL context
incompatibility. Reset to previous "virtual screen" (i.e.,
renderer). OS X's OpenGL implementation will take care of
copying
*/
[context setCurrentVirtualScreen:_virtualScreen];
[[OOGraphicsResetManager sharedManager] resetGraphicsState]; // If this throws, we're screwed.
if ([[self gameController] inFullScreenMode])
{
[[self gameController] pauseFullScreenModeToPerform:@selector(noteMovedToBadDisplay) onTarget:self];
}
else
{
[self noteMovedToBadDisplay];
}
}
}
}
- (void) initialiseGLWithSize:(NSSize) v_size
{
viewSize = v_size;
@ -243,6 +292,12 @@ static NSString * kOOLogKeyDown = @"input.keyMapping.keyPress.keyDown";
}
- (NSData *)pixelFormatAttributes
{
return _pixelFormatAttributes;
}
- (void) snapShot
{
int w = viewSize.width;

View File

@ -575,38 +575,11 @@ static NSComparisonResult CompareDisplayModes(id arg1, id arg2, void *context)
originalDisplayMode = (NSDictionary *)CGDisplayCurrentMode(kCGDirectMainDisplay);
// Pixel Format Attributes for the FullScreen NSOpenGLContext
NSOpenGLPixelFormatAttribute attrs[] = {
NSMutableData *attrData = [[gameView pixelFormatAttributes] mutableCopy];
NSOpenGLPixelFormatAttribute *attrs = [attrData mutableBytes];
NSAssert(attrs[0] == NSOpenGLPFAWindow, @"Pixel format does not meet my strenuous expectations!");
attrs[0] = NSOpenGLPFAFullScreen;
// Specify that we want a full-screen OpenGL context.
NSOpenGLPFAFullScreen,
// // and that we want a windowed OpenGL context.
// NSOpenGLPFAWindow,
// We may be on a multi-display system (and each screen may be driven by a different renderer), so we need to specify which screen we want to take over.
// For this demo, we'll specify the main screen.
NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),
// Specifying "NoRecovery" gives us a context that cannot fall back to the software renderer.
// This makes the View-based context compatible with the fullscreen context, enabling us to use the "shareContext"
// feature to share textures, display lists, and other OpenGL objects between the two.
NSOpenGLPFANoRecovery,
// Attributes Common to FullScreen and non-FullScreen
NSOpenGLPFACompliant,
NSOpenGLPFAColorSize, 32,
NSOpenGLPFADepthSize, 32,
NSOpenGLPFADoubleBuffer,
NSOpenGLPFAAccelerated,
#if FSAA
// Need a preference or other sane way to activate this
NSOpenGLPFAMultisample,
NSOpenGLPFASampleBuffers, 1,
NSOpenGLPFASamples,4,
#endif
0
};
GLint rendererID;
// Create the FullScreen NSOpenGLContext with the attributes listed above.

View File

@ -27,6 +27,7 @@ SOFTWARE.
#import "OOGraphicsResetManager.h"
#import "OOTexture.h"
#import "OOOpenGLExtensionManager.h"
static OOGraphicsResetManager *sSingleton = nil;
@ -76,6 +77,7 @@ static OOGraphicsResetManager *sSingleton = nil;
OOLog(@"rendering.reset.start", @"Resetting graphics state.");
OOLogIndentIf(@"rendering.reset.start");
[[OOOpenGLExtensionManager sharedManager] reset];
[OOTexture rebindAllTextures];
for (clientEnum = [clients objectEnumerator]; (client = [[clientEnum nextObject] pointerValue]); )

View File

@ -149,6 +149,8 @@ SOFTWARE.
+ (id)sharedManager;
- (void) reset;
- (BOOL)haveExtension:(NSString *)extension;
- (BOOL)shadersSupported;

View File

@ -161,8 +161,6 @@ static NSArray *ArrayOfExtensions(NSString *extensionString)
- (id)init
{
const GLubyte *versionString = NULL, *curr = NULL;
self = [super init];
if (self != nil)
{
@ -171,6 +169,21 @@ static NSArray *ArrayOfExtensions(NSString *extensionString)
[lock ooSetName:@"OOOpenGLExtensionManager extension set lock"];
#endif
[self reset];
}
return self;
}
- (void) reset
{
const GLubyte *versionString = NULL, *curr = NULL;
DESTROY(extensions);
DESTROY(vendor);
DESTROY(renderer);
NSString *extensionsStr = [NSString stringWithUTF8String:(char *)glGetString(GL_EXTENSIONS)];
extensions = [[NSSet alloc] initWithArray:ArrayOfExtensions(extensionsStr)];
@ -204,7 +217,7 @@ static NSArray *ArrayOfExtensions(NSString *extensionString)
*/
[ResourceManager paths];
OOLog(@"rendering.opengl.version", @"OpenGL renderer version: %u.%u.%u (\"%s\")\nVendor: %@\nRenderer: %@", major, minor, release, versionString, vendor, renderer);
OOLog(@"rendering.opengl.version", @"OpenGL renderer version: %u.%u.%u (\"%s\"). Vendor: \"%@\". Renderer: \"%@\".", major, minor, release, versionString, vendor, renderer);
OOLog(@"rendering.opengl.extensions", @"OpenGL extensions (%u):\n%@", [extensions count], [[extensions allObjects] componentsJoinedByString:@", "]);
if (![self versionIsAtLeastMajor:kMinMajorVersion minor:kMinMinorVersion])
@ -267,9 +280,6 @@ static NSArray *ArrayOfExtensions(NSString *extensionString)
usePointSmoothing = [gpuConfig oo_boolForKey:@"smooth_points" defaultValue:YES];
useLineSmoothing = [gpuConfig oo_boolForKey:@"smooth_lines" defaultValue:YES];
useDustShader = [gpuConfig oo_boolForKey:@"use_dust_shader" defaultValue:YES];
}
return self;
}
@ -280,9 +290,9 @@ static NSArray *ArrayOfExtensions(NSString *extensionString)
#if OOOPENGLEXTMGR_LOCK_SET_ACCESS
[lock release];
#endif
[extensions release];
[vendor release];
[renderer release];
DESTROY(extensions);
DESTROY(vendor);
DESTROY(renderer);
[super dealloc];
}

View File

@ -192,6 +192,9 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
- (void) filterOutNonStrictEquipment;
- (void) reinitAndShowDemo:(BOOL) showDemo strictChanged:(BOOL) strictChanged;
// Set shader effects level without logging or triggering a reset -- should only be used directly during startup.
- (void) setShaderEffectsLevelDirectly:(OOShaderSetting)value;
@end
@ -208,6 +211,10 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
}
self = [super init];
if (self == nil) return nil;
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[self setGameView:inGameView];
gSharedUniverse = self;
@ -217,13 +224,14 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
// init OpenGL extension manager (must be done before any other threads might use it)
[OOOpenGLExtensionManager sharedManager];
[self setShaderEffectsLevelDirectly:[prefs oo_intForKey:@"shader-mode"
defaultValue:[[OOOpenGLExtensionManager sharedManager] defaultShaderSetting]]];
[OOMaterial setUp];
// Preload cache
[OOCacheManager sharedCache];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
strict = [prefs oo_boolForKey:@"strict-gameplay" defaultValue:NO];
// init the Resource Manager
@ -242,11 +250,6 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
doProcedurallyTexturedPlanets = [prefs oo_boolForKey:@"procedurally-textured-planets" defaultValue:YES];
#endif
BOOL logResets = OOLogWillDisplayMessagesInClass(@"rendering.reset.start");
OOLogSetDisplayMessagesInClass(@"rendering.reset.start", NO);
[self setShaderEffectsLevel:[prefs oo_intForKey:@"shader-mode" defaultValue:[[OOOpenGLExtensionManager sharedManager] defaultShaderSetting]]];
OOLogSetDisplayMessagesInClass(@"rendering.reset.start", logResets);
#if OOLITE_SPEECH_SYNTH
#if OOLITE_MAC_OS_X
//// speech stuff
@ -8386,16 +8389,15 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
- (void) setShaderEffectsLevel:(OOShaderSetting)value transiently:(BOOL)transiently
{
OOShaderSetting max = [[OOOpenGLExtensionManager sharedManager] maximumShaderSetting];
OOShaderSetting old = [self shaderEffectsLevel];
[self setShaderEffectsLevelDirectly:value];
OOShaderSetting new = [self shaderEffectsLevel];
if (value < SHADERS_MIN) value = SHADERS_MIN;
if (max < value) value = max;
if (value != shaderEffectsLevel)
if (old != new)
{
OOLog(@"rendering.opengl.shader.mode", @"Shader mode set to %@.", ShaderSettingToString(value));
shaderEffectsLevel = value;
if (!transiently) [[NSUserDefaults standardUserDefaults] setInteger:shaderEffectsLevel forKey:@"shader-mode"];
[[OOGraphicsResetManager sharedManager] resetGraphicsState];
}
}
@ -9205,7 +9207,7 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
unsigned i = [_preloadingPlanetMaterials count];
while (i--)
{
if (![_preloadingPlanetMaterials objectAtIndex:i] || [[_preloadingPlanetMaterials objectAtIndex:i] isFinishedLoading])
if ([[_preloadingPlanetMaterials objectAtIndex:i] isFinishedLoading])
{
[_preloadingPlanetMaterials removeObjectAtIndex:i];
}
@ -9213,6 +9215,17 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
}
#endif
- (void) setShaderEffectsLevelDirectly:(OOShaderSetting)value
{
OOShaderSetting max = [[OOOpenGLExtensionManager sharedManager] maximumShaderSetting];
if (value < SHADERS_MIN) value = SHADERS_MIN;
if (max < value) value = max;
shaderEffectsLevel = value;
}
@end