LCOV - code coverage report
Current view: top level - Core - OOOpenGLExtensionManager.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 1 18 5.6 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOOpenGLExtensionManager.m
       4             : 
       5             : 
       6             : Copyright (C) 2007-2013 Jens Ayton and contributors
       7             : 
       8             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9             : of this software and associated documentation files (the "Software"), to deal
      10             : in the Software without restriction, including without limitation the rights
      11             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             : copies of the Software, and to permit persons to whom the Software is
      13             : furnished to do so, subject to the following conditions:
      14             : 
      15             : The above copyright notice and this permission notice shall be included in all
      16             : copies or substantial portions of the Software.
      17             : 
      18             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             : SOFTWARE.
      25             : 
      26             : */
      27             : 
      28             : #import "OOOpenGLExtensionManager.h"
      29             : #import "OOLogging.h"
      30             : #import "OOFunctionAttributes.h"
      31             : #include <stdlib.h>
      32             : #import "NSThreadOOExtensions.h"
      33             : 
      34             : #import "ResourceManager.h"
      35             : #import "OOCollectionExtractors.h"
      36             : #import "OORegExpMatcher.h"
      37             : #import "OOConstToString.h"
      38             : 
      39             : 
      40             : /*      OpenGL version required, currently 1.1 or later (basic stuff like
      41             :         glBindTexture(), glDrawArrays()). We probably have implicit requirements
      42             :         for later versions, but I don't feel like auditing.
      43             :         -- Ahruman
      44             :         We need at least 3.0 for the Frame Buffer Objects now in use. Might as
      45             :         well go all the way to 3.3.
      46             :         -- Nikos 20220817
      47             : */
      48           0 : enum
      49             : {
      50             :         kMinMajorVersion                                = 3,
      51             :         kMinMinorVersion                                = 3
      52             : };
      53             : 
      54             : 
      55             : #if OOLITE_WINDOWS
      56             : /*      Define the function pointers for the OpenGL extensions used in the game
      57             :         (required for Windows only).
      58             : */
      59             : static void OOBadOpenGLExtensionUsed(void) GCC_ATTR((noreturn, used));
      60             : 
      61             : #if OO_SHADERS
      62             : 
      63             : PFNGLUSEPROGRAMOBJECTARBPROC                    glUseProgramObjectARB                   = (PFNGLUSEPROGRAMOBJECTARBPROC)&OOBadOpenGLExtensionUsed;
      64             : PFNGLGETUNIFORMLOCATIONARBPROC                  glGetUniformLocationARB                 = (PFNGLGETUNIFORMLOCATIONARBPROC)&OOBadOpenGLExtensionUsed;
      65             : PFNGLUNIFORM1IARBPROC                                   glUniform1iARB                                  = (PFNGLUNIFORM1IARBPROC)&OOBadOpenGLExtensionUsed;
      66             : PFNGLUNIFORM1FARBPROC                                   glUniform1fARB                                  = (PFNGLUNIFORM1FARBPROC)&OOBadOpenGLExtensionUsed;
      67             : PFNGLUNIFORMMATRIX3FVARBPROC                    glUniformMatrix3fvARB                   = (PFNGLUNIFORMMATRIX3FVARBPROC)&OOBadOpenGLExtensionUsed;
      68             : PFNGLUNIFORMMATRIX4FVARBPROC                    glUniformMatrix4fvARB                   = (PFNGLUNIFORMMATRIX4FVARBPROC)&OOBadOpenGLExtensionUsed;
      69             : PFNGLUNIFORM4FVARBPROC                                  glUniform4fvARB                                 = (PFNGLUNIFORM4FVARBPROC)&OOBadOpenGLExtensionUsed;
      70             : PFNGLGETOBJECTPARAMETERIVARBPROC                glGetObjectParameterivARB               = (PFNGLGETOBJECTPARAMETERIVARBPROC)&OOBadOpenGLExtensionUsed;
      71             : PFNGLCREATESHADEROBJECTARBPROC                  glCreateShaderObjectARB                 = (PFNGLCREATESHADEROBJECTARBPROC)&OOBadOpenGLExtensionUsed;
      72             : PFNGLGETINFOLOGARBPROC                                  glGetInfoLogARB                                 = (PFNGLGETINFOLOGARBPROC)&OOBadOpenGLExtensionUsed;
      73             : PFNGLCREATEPROGRAMOBJECTARBPROC                 glCreateProgramObjectARB                = (PFNGLCREATEPROGRAMOBJECTARBPROC)&OOBadOpenGLExtensionUsed;
      74             : PFNGLATTACHOBJECTARBPROC                                glAttachObjectARB                               = (PFNGLATTACHOBJECTARBPROC)&OOBadOpenGLExtensionUsed;
      75             : PFNGLDELETEOBJECTARBPROC                                glDeleteObjectARB                               = (PFNGLDELETEOBJECTARBPROC)&OOBadOpenGLExtensionUsed;
      76             : PFNGLLINKPROGRAMARBPROC                                 glLinkProgramARB                                = (PFNGLLINKPROGRAMARBPROC)&OOBadOpenGLExtensionUsed;
      77             : PFNGLCOMPILESHADERARBPROC                               glCompileShaderARB                              = (PFNGLCOMPILESHADERARBPROC)&OOBadOpenGLExtensionUsed;
      78             : PFNGLSHADERSOURCEARBPROC                                glShaderSourceARB                               = (PFNGLSHADERSOURCEARBPROC)&OOBadOpenGLExtensionUsed;
      79             : PFNGLUNIFORM2FVARBPROC                                  glUniform2fvARB                                 = (PFNGLUNIFORM2FVARBPROC)&OOBadOpenGLExtensionUsed;
      80             : PFNGLBINDATTRIBLOCATIONARBPROC                  glBindAttribLocationARB                 = (PFNGLBINDATTRIBLOCATIONARBPROC)&OOBadOpenGLExtensionUsed;
      81             : PFNGLENABLEVERTEXATTRIBARRAYARBPROC             glEnableVertexAttribArrayARB    = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)&OOBadOpenGLExtensionUsed;
      82             : PFNGLVERTEXATTRIBPOINTERARBPROC                 glVertexAttribPointerARB                = (PFNGLVERTEXATTRIBPOINTERARBPROC)&OOBadOpenGLExtensionUsed;
      83             : PFNGLDISABLEVERTEXATTRIBARRAYARBPROC    glDisableVertexAttribArrayARB   = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)&OOBadOpenGLExtensionUsed;
      84             : PFNGLVALIDATEPROGRAMARBPROC                     glValidateProgramARB                    = (PFNGLVALIDATEPROGRAMARBPROC)&OOBadOpenGLExtensionUsed;
      85             : #endif
      86             : 
      87             : #if OO_SHADERS || OO_MULTITEXTURE
      88             : PFNGLACTIVETEXTUREARBPROC                               glActiveTextureARB                              = (PFNGLACTIVETEXTUREARBPROC)&OOBadOpenGLExtensionUsed;
      89             : #endif
      90             : 
      91             : #if OO_MULTITEXTURE
      92             : PFNGLCLIENTACTIVETEXTUREARBPROC                 glClientActiveTextureARB                = (PFNGLCLIENTACTIVETEXTUREARBPROC)&OOBadOpenGLExtensionUsed;
      93             : #endif
      94             : 
      95             : #if OO_USE_VBO
      96             : PFNGLGENBUFFERSARBPROC                                  glGenBuffersARB                                 = (PFNGLGENBUFFERSARBPROC)&OOBadOpenGLExtensionUsed;
      97             : PFNGLDELETEBUFFERSARBPROC                               glDeleteBuffersARB                              = (PFNGLDELETEBUFFERSARBPROC)&OOBadOpenGLExtensionUsed;
      98             : PFNGLBINDBUFFERARBPROC                                  glBindBufferARB                                 = (PFNGLBINDBUFFERARBPROC)&OOBadOpenGLExtensionUsed;
      99             : PFNGLBUFFERDATAARBPROC                                  glBufferDataARB                                 = (PFNGLBUFFERDATAARBPROC)&OOBadOpenGLExtensionUsed;
     100             : #endif
     101             : 
     102             : #if OO_USE_FBO
     103             : PFNGLGENFRAMEBUFFERSEXTPROC                             glGenFramebuffersEXT                    = (PFNGLGENFRAMEBUFFERSEXTPROC)&OOBadOpenGLExtensionUsed;
     104             : PFNGLBINDFRAMEBUFFEREXTPROC                             glBindFramebufferEXT                    = (PFNGLBINDFRAMEBUFFEREXTPROC)&OOBadOpenGLExtensionUsed;
     105             : PFNGLGENRENDERBUFFERSEXTPROC                    glGenRenderbuffersEXT                   = (PFNGLGENRENDERBUFFERSEXTPROC)&OOBadOpenGLExtensionUsed;
     106             : PFNGLBINDRENDERBUFFEREXTPROC                    glBindRenderbufferEXT                   = (PFNGLBINDRENDERBUFFEREXTPROC)&OOBadOpenGLExtensionUsed;
     107             : PFNGLRENDERBUFFERSTORAGEEXTPROC                 glRenderbufferStorageEXT                = (PFNGLRENDERBUFFERSTORAGEEXTPROC)&OOBadOpenGLExtensionUsed;
     108             : PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC             glFramebufferRenderbufferEXT    = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)&OOBadOpenGLExtensionUsed;
     109             : PFNGLFRAMEBUFFERTEXTURE2DEXTPROC                glFramebufferTexture2DEXT               = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)&OOBadOpenGLExtensionUsed;
     110             : PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC              glCheckFramebufferStatusEXT             = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)&OOBadOpenGLExtensionUsed;
     111             : PFNGLDELETEFRAMEBUFFERSEXTPROC                  glDeleteFramebuffersEXT                 = (PFNGLDELETEFRAMEBUFFERSEXTPROC)&OOBadOpenGLExtensionUsed;
     112             : PFNGLDELETERENDERBUFFERSEXTPROC                 glDeleteRenderbuffersEXT                = (PFNGLDELETERENDERBUFFERSEXTPROC)&OOBadOpenGLExtensionUsed;
     113             : PFNGLGENRENDERBUFFERSPROC                               glGenRenderbuffers                              = (PFNGLGENRENDERBUFFERSPROC)&OOBadOpenGLExtensionUsed;
     114             : PFNGLBINDRENDERBUFFERPROC                               glBindRenderbuffer                              = (PFNGLBINDRENDERBUFFERPROC)&OOBadOpenGLExtensionUsed;              
     115             : PFNGLRENDERBUFFERSTORAGEPROC                    glRenderbufferStorage                   = (PFNGLRENDERBUFFERSTORAGEPROC)&OOBadOpenGLExtensionUsed;    
     116             : PFNGLGENFRAMEBUFFERSPROC                                glGenFramebuffers                               = (PFNGLGENFRAMEBUFFERSPROC)&OOBadOpenGLExtensionUsed;                
     117             : PFNGLBINDFRAMEBUFFERPROC                                glBindFramebuffer                               = (PFNGLBINDFRAMEBUFFERPROC)&OOBadOpenGLExtensionUsed;                
     118             : PFNGLFRAMEBUFFERRENDERBUFFERPROC                glFramebufferRenderbuffer               = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)&OOBadOpenGLExtensionUsed;  
     119             : PFNGLFRAMEBUFFERTEXTURE2DPROC                   glFramebufferTexture2D                  = (PFNGLFRAMEBUFFERTEXTURE2DPROC)&OOBadOpenGLExtensionUsed;   
     120             : PFNGLGENVERTEXARRAYSPROC                                glGenVertexArrays                               = (PFNGLGENVERTEXARRAYSPROC)&OOBadOpenGLExtensionUsed;                
     121             : PFNGLGENBUFFERSPROC                                             glGenBuffers                                    = (PFNGLGENBUFFERSPROC)&OOBadOpenGLExtensionUsed;                             
     122             : PFNGLBINDVERTEXARRAYPROC                                glBindVertexArray                               = (PFNGLBINDVERTEXARRAYPROC)&OOBadOpenGLExtensionUsed;                
     123             : PFNGLBINDBUFFERPROC                                             glBindBuffer                                    = (PFNGLBINDBUFFERPROC)&OOBadOpenGLExtensionUsed;                             
     124             : PFNGLBUFFERDATAPROC                                             glBufferData                                    = (PFNGLBUFFERDATAPROC)&OOBadOpenGLExtensionUsed;                             
     125             : PFNGLVERTEXATTRIBPOINTERPROC                    glVertexAttribPointer                   = (PFNGLVERTEXATTRIBPOINTERPROC)&OOBadOpenGLExtensionUsed;    
     126             : PFNGLENABLEVERTEXATTRIBARRAYPROC                glEnableVertexAttribArray               = (PFNGLENABLEVERTEXATTRIBARRAYPROC)&OOBadOpenGLExtensionUsed;  
     127             : PFNGLUSEPROGRAMPROC                                             glUseProgram                                    = (PFNGLUSEPROGRAMPROC)&OOBadOpenGLExtensionUsed;                             
     128             : PFNGLGETUNIFORMLOCATIONPROC                             glGetUniformLocation                    = (PFNGLGETUNIFORMLOCATIONPROC)&OOBadOpenGLExtensionUsed;             
     129             : PFNGLUNIFORM1IPROC                                              glUniform1i                                             = (PFNGLUNIFORM1IPROC)&OOBadOpenGLExtensionUsed;                              
     130             : PFNGLACTIVETEXTUREPROC                                  glActiveTexture                                 = (PFNGLACTIVETEXTUREPROC)&OOBadOpenGLExtensionUsed;
     131             : PFNGLBLENDFUNCSEPARATEPROC                              glBlendFuncSeparate                             = (PFNGLBLENDFUNCSEPARATEPROC)&OOBadOpenGLExtensionUsed;
     132             : PFNGLUNIFORM1FPROC                                              glUniform1f                                             = (PFNGLUNIFORM1FPROC)&OOBadOpenGLExtensionUsed;
     133             : PFNGLUNIFORM2FVPROC                                             glUniform2fv                                    = (PFNGLUNIFORM2FVPROC)&OOBadOpenGLExtensionUsed;
     134             : PFNGLDELETERENDERBUFFERSPROC                    glDeleteRenderbuffers                   = (PFNGLDELETERENDERBUFFERSPROC)&OOBadOpenGLExtensionUsed;
     135             : PFNGLDELETEFRAMEBUFFERSPROC                             glDeleteFramebuffers                    = (PFNGLDELETEFRAMEBUFFERSPROC)&OOBadOpenGLExtensionUsed;
     136             : PFNGLDELETEVERTEXARRAYSPROC                             glDeleteVertexArrays                    = (PFNGLDELETEVERTEXARRAYSPROC)&OOBadOpenGLExtensionUsed;
     137             : PFNGLDELETEBUFFERSPROC                                  glDeleteBuffers                                 = (PFNGLDELETEBUFFERSPROC)&OOBadOpenGLExtensionUsed;
     138             : PFNGLDRAWBUFFERSPROC                                            glDrawBuffers                                   = (PFNGLDRAWBUFFERSPROC)&OOBadOpenGLExtensionUsed;
     139             : PFNGLCHECKFRAMEBUFFERSTATUSPROC                 glCheckFramebufferStatus                        = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)&OOBadOpenGLExtensionUsed;
     140             : PFNGLTEXIMAGE2DMULTISAMPLEPROC                          glTexImage2DMultisample                 = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)&OOBadOpenGLExtensionUsed;
     141             : PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC         glRenderbufferStorageMultisample        = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)&OOBadOpenGLExtensionUsed;
     142             : PFNGLBLITFRAMEBUFFERPROC                                        glBlitFramebuffer                                       = (PFNGLBLITFRAMEBUFFERPROC)&OOBadOpenGLExtensionUsed;
     143             : PFNGLCLAMPCOLORPROC                                             glClampColor                                    = (PFNGLCLAMPCOLORPROC)&OOBadOpenGLExtensionUsed;
     144             : #endif                                                                    
     145             : #endif
     146             : 
     147             : 
     148           0 : static NSString * const kOOLogOpenGLShaderSupport               = @"rendering.opengl.shader.support";
     149             : 
     150             : 
     151           0 : static OOOpenGLExtensionManager *sSingleton = nil;
     152             : 
     153             : 
     154             : // Read integer from string, advancing string to end of read data.
     155             : static unsigned IntegerFromString(const GLubyte **ioString);
     156             : 
     157             : 
     158             : @interface OOOpenGLExtensionManager (OOPrivate)
     159             : 
     160             : #if OO_SHADERS
     161           1 : - (void)checkShadersSupported;
     162             : #endif
     163             : 
     164             : #if OO_USE_VBO
     165             : - (void)checkVBOSupported;
     166             : #endif
     167             : 
     168             : #if OO_USE_FBO
     169             : - (void)checkFBOSupported;
     170             : #endif
     171             : 
     172             : #if GL_ARB_texture_env_combine
     173             : - (void)checkTextureCombinersSupported;
     174             : #endif
     175             : 
     176           0 : - (NSDictionary *) lookUpPerGPUSettingsWithVersionString:(NSString *)version extensionsString:(NSString *)extensionsStr;
     177             : 
     178             : @end
     179             : 
     180             : 
     181           0 : static NSArray *ArrayOfExtensions(NSString *extensionString)
     182             : {
     183             :         NSArray *components = [extensionString componentsSeparatedByString:@" "];
     184             :         NSMutableArray *result = [NSMutableArray arrayWithCapacity:[components count]];
     185             :         NSEnumerator *extEnum = nil;
     186             :         NSString *extStr = nil;
     187             :         for (extEnum = [components objectEnumerator]; (extStr = [extEnum nextObject]); )
     188             :         {
     189             :                 if ([extStr length] > 0)  [result addObject:extStr];
     190             :         }
     191             :         return result;
     192             : }
     193             : 
     194             : 
     195             : @implementation OOOpenGLExtensionManager
     196             : 
     197           0 : - (id)init
     198             : {
     199             :         self = [super init];
     200             :         if (self != nil)
     201             :         {
     202             : #if OOOPENGLEXTMGR_LOCK_SET_ACCESS
     203             :                 lock = [[NSLock alloc] init];
     204             :                 [lock setName:@"OOOpenGLExtensionManager extension set lock"];
     205             : #endif
     206             :                 
     207             :                 [self reset];
     208             :         }
     209             :         
     210             :         return self;
     211             : }
     212             : 
     213             : 
     214             : - (void) reset
     215             : {
     216             :         const GLubyte           *versionString = NULL, *curr = NULL;
     217             :         
     218             :         DESTROY(extensions);
     219             :         DESTROY(vendor);
     220             :         DESTROY(renderer);
     221             :         
     222             :         NSString *extensionsStr = [NSString stringWithUTF8String:(char *)glGetString(GL_EXTENSIONS)];
     223             :         extensions = [[NSSet alloc] initWithArray:ArrayOfExtensions(extensionsStr)];
     224             :         
     225             :         vendor = [[NSString alloc] initWithUTF8String:(const char *)glGetString(GL_VENDOR)];
     226             :         renderer = [[NSString alloc] initWithUTF8String:(const char *)glGetString(GL_RENDERER)];
     227             :         
     228             :         versionString = glGetString(GL_VERSION);
     229             :         if (versionString != NULL)
     230             :         {
     231             :                 /*      String is supposed to be "major.minorFOO" or
     232             :                  "major.minor.releaseFOO" where FOO is an empty string or
     233             :                  a string beginning with space.
     234             :                  */
     235             :                 curr = versionString;
     236             :                 major = IntegerFromString(&curr);
     237             :                 if (*curr == '.')
     238             :                 {
     239             :                         curr++;
     240             :                         minor = IntegerFromString(&curr);
     241             :                 }
     242             :                 if (*curr == '.')
     243             :                 {
     244             :                         curr++;
     245             :                         release = IntegerFromString(&curr);
     246             :                 }
     247             :         }
     248             :         
     249             :         /*      For aesthetic reasons, cause the ResourceManager to initialize its
     250             :          search paths here. If we don't, the search path dump ends up in
     251             :          the middle of the OpenGL stuff.
     252             :          */
     253             :         [ResourceManager paths];
     254             :         
     255             :         OOLog(@"rendering.opengl.version", @"OpenGL renderer version: %u.%u.%u (\"%s\"). Vendor: \"%@\". Renderer: \"%@\".", major, minor, release, versionString, vendor, renderer);
     256             :         OOLog(@"rendering.opengl.extensions", @"OpenGL extensions (%lu):\n%@", [extensions count], [[extensions allObjects] componentsJoinedByString:@", "]);
     257             :         
     258             :         if (![self versionIsAtLeastMajor:kMinMajorVersion minor:kMinMinorVersion])
     259             :         {
     260             :                 OOLog(@"rendering.opengl.version.insufficient", @"***** Oolite requires OpenGL version %u.%u or later.", kMinMajorVersion, kMinMinorVersion);
     261             :                 [NSException raise:@"OoliteOpenGLTooOldException"
     262             :                                         format:@"Oolite requires at least OpenGL %u.%u. You have %u.%u (\"%s\").", kMinMajorVersion, kMinMinorVersion, major, minor, versionString];
     263             :         }
     264             :         
     265             :         NSString *versionStr = [[[NSString alloc] initWithUTF8String:(const char *)versionString] autorelease];
     266             :         NSDictionary *gpuConfig = [self lookUpPerGPUSettingsWithVersionString:versionStr extensionsString:extensionsStr];
     267             :         
     268             : #if OO_SHADERS
     269             :         [self checkShadersSupported];
     270             :         
     271             :         if (shadersAvailable)
     272             :         {
     273             :                 defaultShaderSetting = OOShaderSettingFromString([gpuConfig oo_stringForKey:@"default_shader_level"
     274             :                                                                                                                                    defaultValue:@"SHADERS_FULL"]);
     275             :                 maximumShaderSetting = OOShaderSettingFromString([gpuConfig oo_stringForKey:@"maximum_shader_level"
     276             :                                                                                                                                    defaultValue:@"SHADERS_FULL"]);
     277             :                 if (maximumShaderSetting <= SHADERS_OFF)
     278             :                 {
     279             :                         shadersAvailable = NO;
     280             :                         maximumShaderSetting = SHADERS_NOT_SUPPORTED;
     281             :                         OOLog(kOOLogOpenGLShaderSupport, @"Shaders will not be used (disallowed for GPU type \"%@\").", [gpuConfig oo_stringForKey:@"name" defaultValue:renderer]);
     282             :                 }
     283             :                 if (maximumShaderSetting < defaultShaderSetting)
     284             :                 {
     285             :                         defaultShaderSetting = maximumShaderSetting;
     286             :                 }
     287             :                 
     288             :                 if (shadersAvailable)
     289             :                 {
     290             :                         OOLog(kOOLogOpenGLShaderSupport, @"%@", @"Shaders are supported.");
     291             :                 }
     292             :         }
     293             :         else
     294             :         {
     295             :                 defaultShaderSetting = SHADERS_NOT_SUPPORTED;
     296             :                 maximumShaderSetting = SHADERS_NOT_SUPPORTED;
     297             :         }
     298             :         
     299             :         GLint texImageUnitOverride = [gpuConfig oo_intForKey:@"texture_image_units" defaultValue:textureImageUnitCount];
     300             :         if (texImageUnitOverride < textureImageUnitCount)  textureImageUnitCount = MAX(texImageUnitOverride, 0);
     301             : #endif
     302             :         
     303             : #if OO_USE_VBO
     304             :         [self checkVBOSupported];
     305             : #endif
     306             : #if OO_USE_FBO
     307             :         [self checkFBOSupported];
     308             : #endif
     309             : #if OO_MULTITEXTURE
     310             :         [self checkTextureCombinersSupported];
     311             :         GLint texUnitOverride = [gpuConfig oo_intForKey:@"texture_units" defaultValue:textureUnitCount];
     312             :         if (texUnitOverride < textureUnitCount)  textureUnitCount = MAX(texUnitOverride, 0);
     313             : #endif
     314             :         
     315             :         usePointSmoothing = [gpuConfig oo_boolForKey:@"smooth_points" defaultValue:YES];
     316             :         useLineSmoothing = [gpuConfig oo_boolForKey:@"smooth_lines" defaultValue:YES];
     317             :         useDustShader = [gpuConfig oo_boolForKey:@"use_dust_shader" defaultValue:YES];
     318             : }
     319             : 
     320             : 
     321           0 : - (void)dealloc
     322             : {
     323             :         if (sSingleton == self)  sSingleton = nil;
     324             :         
     325             : #if OOOPENGLEXTMGR_LOCK_SET_ACCESS
     326             :         [lock release];
     327             : #endif
     328             :         DESTROY(extensions);
     329             :         DESTROY(vendor);
     330             :         DESTROY(renderer);
     331             :         
     332             :         [super dealloc];
     333             : }
     334             : 
     335             : 
     336             : + (OOOpenGLExtensionManager *)sharedManager
     337             : {
     338             :         // NOTE: assumes single-threaded first access. See header.
     339             :         if (sSingleton == nil)  sSingleton = [[self alloc] init];
     340             :         return sSingleton;
     341             : }
     342             : 
     343             : 
     344             : - (BOOL)haveExtension:(NSString *)extension
     345             : {
     346             : // NSSet is documented as thread-safe under OS X, but I'm not sure about GNUstep. -- Ahruman
     347             : #if OOOPENGLEXTMGR_LOCK_SET_ACCESS
     348             :         [lock lock];
     349             : #endif
     350             :         
     351             :         BOOL result = [extensions containsObject:extension];
     352             :         
     353             : #if OOOPENGLEXTMGR_LOCK_SET_ACCESS
     354             :         [lock unlock];
     355             : #endif
     356             :         
     357             :         return result;
     358             : }
     359             : 
     360             : 
     361             : - (BOOL)shadersSupported
     362             : {
     363             : #if OO_SHADERS
     364             :         return shadersAvailable;
     365             : #else
     366             :         return NO;
     367             : #endif
     368             : }
     369             : 
     370             : 
     371             : - (BOOL)shadersForceDisabled
     372             : {
     373             : #if OO_SHADERS
     374             :         return shadersForceDisabled;
     375             : #else
     376             :         return YES;
     377             : #endif
     378             : }
     379             : 
     380             : 
     381             : - (OOGraphicsDetail)defaultDetailLevel
     382             : {
     383             : #if OO_SHADERS
     384             :         if (defaultShaderSetting < SHADERS_FULL)
     385             :         {
     386             :                 return DETAIL_LEVEL_MINIMUM;
     387             :         }
     388             :         else
     389             :         {
     390             :                 return DETAIL_LEVEL_MAXIMUM;
     391             :         }
     392             : #else
     393             :         return SHADERS_NOT_SUPPORTED;
     394             : #endif
     395             : }
     396             : 
     397             : 
     398             : - (OOGraphicsDetail)maximumDetailLevel
     399             : {
     400             : #if OO_SHADERS
     401             :         if (maximumShaderSetting < SHADERS_FULL)
     402             :         {
     403             :                 return DETAIL_LEVEL_MINIMUM;
     404             :         }
     405             :         else
     406             :         {
     407             :                 return DETAIL_LEVEL_MAXIMUM;
     408             :         }
     409             : #else
     410             :         return DETAIL_LEVEL_MINIMUM;
     411             : #endif
     412             : }
     413             : 
     414             : 
     415             : - (GLint)textureImageUnitCount
     416             : {
     417             : #if OO_SHADERS
     418             :         return textureImageUnitCount;
     419             : #else
     420             :         return 0;
     421             : #endif
     422             : }
     423             : 
     424             : 
     425             : - (BOOL)vboSupported
     426             : {
     427             : #if OO_USE_VBO
     428             :         return vboSupported;
     429             : #else
     430             :         return NO;
     431             : #endif
     432             : }
     433             : 
     434             : 
     435             : - (BOOL)fboSupported
     436             : {
     437             : #if OO_USE_FBO
     438             :         return fboSupported;
     439             : #else
     440             :         return NO;
     441             : #endif
     442             : }
     443             : 
     444             : 
     445             : - (BOOL)textureCombinersSupported
     446             : {
     447             : #if OO_MULTITEXTURE
     448             :         return textureCombinersSupported;
     449             : #else
     450             :         return NO;
     451             : #endif
     452             : }
     453             : 
     454             : 
     455             : - (GLint)textureUnitCount
     456             : {
     457             : #if OO_MULTITEXTURE
     458             :         return textureUnitCount;
     459             : #else
     460             :         return 0;
     461             : #endif
     462             : }
     463             : 
     464             : 
     465             : - (NSUInteger)majorVersionNumber
     466             : {
     467             :         return major;
     468             : }
     469             : 
     470             : 
     471             : - (NSUInteger)minorVersionNumber
     472             : {
     473             :         return minor;
     474             : }
     475             : 
     476             : 
     477             : - (NSUInteger)releaseVersionNumber
     478             : {
     479             :         return release;
     480             : }
     481             : 
     482             : 
     483             : - (void)getVersionMajor:(unsigned *)outMajor minor:(unsigned *)outMinor release:(unsigned *)outRelease
     484             : {
     485             :         if (outMajor != NULL)  *outMajor = major;
     486             :         if (outMinor != NULL)  *outMinor = minor;
     487             :         if (outRelease != NULL)  *outRelease = release;
     488             : }
     489             : 
     490             : 
     491             : - (BOOL) versionIsAtLeastMajor:(unsigned)maj minor:(unsigned)min
     492             : {
     493             :         return major > maj || (major == maj && minor >= min);
     494             : }
     495             : 
     496             : 
     497             : - (NSString *) vendorString
     498             : {
     499             :         return vendor;
     500             : }
     501             : 
     502             : 
     503             : - (NSString *) rendererString
     504             : {
     505             :         return renderer;
     506             : }
     507             : 
     508             : 
     509             : - (BOOL) usePointSmoothing
     510             : {
     511             :         return usePointSmoothing;
     512             : }
     513             : 
     514             : 
     515             : - (BOOL) useLineSmoothing
     516             : {
     517             :         return useLineSmoothing;
     518             : }
     519             : 
     520             : 
     521             : - (BOOL) useDustShader
     522             : {
     523             :         return useDustShader;
     524             : }
     525             : 
     526             : @end
     527             : 
     528             : 
     529           0 : static unsigned IntegerFromString(const GLubyte **ioString)
     530             : {
     531             :         if (EXPECT_NOT(ioString == NULL))  return 0;
     532             :         
     533             :         unsigned                result = 0;
     534             :         const GLubyte   *curr = *ioString;
     535             :         
     536             :         while ('0' <= *curr && *curr <= '9')
     537             :         {
     538             :                 result = result * 10 + *curr++ - '0';
     539             :         }
     540             :         
     541             :         *ioString = curr;
     542             :         return result;
     543             : }
     544             : 
     545             : 
     546             : @implementation OOOpenGLExtensionManager (OOPrivate)
     547             : 
     548             : 
     549             : #if OO_SHADERS
     550             : 
     551             : /**
     552             :  * \ingroup cli
     553             :  * Scans the command line for -noshaders or --noshaders arguments.
     554             :  */
     555             : - (void)checkShadersSupported
     556             : {
     557             :         shadersAvailable = NO;
     558             :         shadersForceDisabled = NO;
     559             : 
     560             :         /* Some cards claim to support shaders but do so extremely
     561             :          * badly. These are listed in gpu-settings.plist where we know
     562             :          * about them; for those we don't being able to run with
     563             :          * -noshaders may help get the game up and running at a frame rate
     564             :          * where thegraphics settings can be changed.  - CIM */
     565             :         NSArray                 *arguments = [[NSProcessInfo processInfo] arguments];
     566             :         NSEnumerator    *argEnum = nil;
     567             :         NSString                *arg = nil;
     568             :         // scan for shader overrides: -noshaders || --noshaders
     569             :         for (argEnum = [arguments objectEnumerator]; (arg = [argEnum nextObject]); )
     570             :         {
     571             :                 if ([arg isEqual:@"-noshaders"] || [arg isEqual:@"--noshaders"])
     572             :                 {
     573             :                         shadersForceDisabled = YES;
     574             :                         OOLog(kOOLogOpenGLShaderSupport, @"%@", @"Shaders will not be used (disabled on command line).");
     575             :                         return;
     576             :                 }
     577             :         }       
     578             : 
     579             :         NSString * const requiredExtension[] = 
     580             :                                                 {
     581             :                                                         @"GL_ARB_shading_language_100",
     582             :                                                         @"GL_ARB_fragment_shader",
     583             :                                                         @"GL_ARB_vertex_shader",
     584             :                                                         @"GL_ARB_multitexture",
     585             :                                                         @"GL_ARB_shader_objects",
     586             :                                                         nil     // sentinel - don't remove!
     587             :                                                 };
     588             :         NSString * const *required = NULL;
     589             :         
     590             :         for (required = requiredExtension; *required != nil; ++required)
     591             :         {
     592             :                 if (![self haveExtension:*required])
     593             :                 {
     594             :                         OOLog(kOOLogOpenGLShaderSupport, @"Shaders will not be used (OpenGL extension %@ is not available).", *required);
     595             :                         return;
     596             :                 }
     597             :         }
     598             :         
     599             : #if OOLITE_WINDOWS
     600             :         glGetObjectParameterivARB       =       (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
     601             :         glCreateShaderObjectARB         =       (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
     602             :         glGetInfoLogARB                         =       (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
     603             :         glCreateProgramObjectARB        =       (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
     604             :         glAttachObjectARB                       =       (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
     605             :         glDeleteObjectARB                       =       (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
     606             :         glLinkProgramARB                        =       (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
     607             :         glCompileShaderARB                      =       (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
     608             :         glShaderSourceARB                       =       (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
     609             :         glUseProgramObjectARB           =       (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
     610             :         glActiveTextureARB                      =       (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
     611             :         glGetUniformLocationARB         =       (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
     612             :         glUniform1iARB                          =       (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
     613             :         glUniform1fARB                          =       (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
     614             :         glUniformMatrix3fvARB           =       (PFNGLUNIFORMMATRIX3FVARBPROC)wglGetProcAddress("glUniformMatrix3fvARB");
     615             :         glUniformMatrix4fvARB           =       (PFNGLUNIFORMMATRIX4FVARBPROC)wglGetProcAddress("glUniformMatrix4fvARB");
     616             :         glUniform4fvARB                         =       (PFNGLUNIFORM4FVARBPROC)wglGetProcAddress("glUniform4fvARB");
     617             :         glUniform2fvARB                         =       (PFNGLUNIFORM2FVARBPROC)wglGetProcAddress("glUniform2fvARB");
     618             :         glBindAttribLocationARB         =       (PFNGLBINDATTRIBLOCATIONARBPROC)wglGetProcAddress("glBindAttribLocationARB");
     619             :         glEnableVertexAttribArrayARB =  (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)wglGetProcAddress("glEnableVertexAttribArrayARB");
     620             :         glVertexAttribPointerARB        =       (PFNGLVERTEXATTRIBPOINTERARBPROC)wglGetProcAddress("glVertexAttribPointerARB");
     621             :         glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)wglGetProcAddress("glDisableVertexAttribArrayARB");
     622             :         glValidateProgramARB            =       (PFNGLVALIDATEPROGRAMARBPROC)wglGetProcAddress("glValidateProgramARB");
     623             : #endif
     624             :         
     625             :         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &textureImageUnitCount);
     626             :         
     627             :         shadersAvailable = YES;
     628             : }
     629             : #endif
     630             : 
     631             : 
     632             : #if OO_USE_VBO
     633             : - (void)checkVBOSupported
     634             : {
     635             :         vboSupported = NO;
     636             :         
     637             :         if ([self versionIsAtLeastMajor:1 minor:5] || [self haveExtension:@"GL_ARB_vertex_buffer_object"])
     638             :         {
     639             :                 vboSupported = YES;
     640             :         }
     641             :         
     642             : #if OOLITE_WINDOWS
     643             :         if (vboSupported)
     644             :         {
     645             :                 glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
     646             :                 glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
     647             :                 glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
     648             :                 glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
     649             :         }
     650             : #endif
     651             : }
     652             : #endif
     653             : 
     654             : 
     655             : #if OO_USE_FBO
     656             : - (void)checkFBOSupported
     657             : {
     658             :         fboSupported = NO;
     659             :         
     660             :         if ([self haveExtension:@"GL_EXT_framebuffer_object"])
     661             :         {
     662             :                 fboSupported = YES;
     663             :         }
     664             :         
     665             : #if OOLITE_WINDOWS
     666             :         if (fboSupported)
     667             :         {
     668             :                 glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
     669             :                 glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
     670             :                 glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
     671             :                 glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
     672             :                 glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
     673             :                 glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
     674             :                 glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
     675             :                 glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
     676             :                 glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
     677             :                 glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
     678             :                 glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)wglGetProcAddress("glGenRenderbuffers");
     679             :                 glBindRenderbuffer                      = (PFNGLBINDRENDERBUFFERPROC)wglGetProcAddress                  ("glBindRenderbuffer"                 );
     680             :                 glRenderbufferStorage           = (PFNGLRENDERBUFFERSTORAGEPROC)wglGetProcAddress               ("glRenderbufferStorage"              );
     681             :                 glGenFramebuffers                       = (PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress                   ("glGenFramebuffers"                  );
     682             :                 glBindFramebuffer                       = (PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress                   ("glBindFramebuffer"                  );
     683             :                 glFramebufferRenderbuffer       = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress   ("glFramebufferRenderbuffer"  );
     684             :                 glFramebufferTexture2D          = (PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress              ("glFramebufferTexture2D"             );
     685             :                 glGenVertexArrays                       = (PFNGLGENVERTEXARRAYSPROC)wglGetProcAddress                   ("glGenVertexArrays"                  );
     686             :                 glGenBuffers                            = (PFNGLGENBUFFERSPROC)wglGetProcAddress                                ("glGenBuffers"                                       );
     687             :                 glBindVertexArray                       = (PFNGLBINDVERTEXARRAYPROC)wglGetProcAddress                   ("glBindVertexArray"                  );
     688             :                 glBindBuffer                            = (PFNGLBINDBUFFERPROC)wglGetProcAddress                                ("glBindBuffer"                                       );
     689             :                 glBufferData                            = (PFNGLBUFFERDATAPROC)wglGetProcAddress                                ("glBufferData"                                       );
     690             :                 glVertexAttribPointer           = (PFNGLVERTEXATTRIBPOINTERPROC)wglGetProcAddress               ("glVertexAttribPointer"              );
     691             :                 glEnableVertexAttribArray       = (PFNGLENABLEVERTEXATTRIBARRAYPROC)wglGetProcAddress   ("glEnableVertexAttribArray"  );
     692             :                 glUseProgram                            = (PFNGLUSEPROGRAMPROC) wglGetProcAddress                               ("glUseProgram"                                       );
     693             :                 glGetUniformLocation            = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress                ("glGetUniformLocation"                       );
     694             :                 glUniform1i                                     = (PFNGLUNIFORM1IPROC)wglGetProcAddress                                 ("glUniform1i"                                        );
     695             :                 glActiveTexture                         = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress                             ("glActiveTexture"                            );
     696             :                 glBlendFuncSeparate                     = (PFNGLBLENDFUNCSEPARATEPROC)wglGetProcAddress                 ("glBlendFuncSeparate"                        );
     697             :                 glUniform1f                                     = (PFNGLUNIFORM1FPROC)wglGetProcAddress                                 ("glUniform1f"                                        );
     698             :                 glUniform2fv                            = (PFNGLUNIFORM2FVPROC)wglGetProcAddress                                ("glUniform2fv"                                       );
     699             :                 glDeleteRenderbuffers           = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress               ("glDeleteRenderbuffer"                       );
     700             :                 glDeleteFramebuffers            = (PFNGLDELETEFRAMEBUFFERSPROC)wglGetProcAddress                ("glDeleteFramebuffers"                       );
     701             :                 glDeleteVertexArrays            = (PFNGLDELETEVERTEXARRAYSPROC)wglGetProcAddress                ("glDeleteVertexArrays"                       );
     702             :                 glDeleteBuffers                         = (PFNGLDELETEBUFFERSPROC)wglGetProcAddress                             ("glDeleteBuffers"                            );
     703             :                 glDrawBuffers                           = (PFNGLDRAWBUFFERSPROC)wglGetProcAddress                               ("glDrawBuffers"                              );
     704             :                 glCheckFramebufferStatus                = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress            ("glCheckFramebufferStatus"                           );
     705             :                 glTexImage2DMultisample         = (PFNGLTEXIMAGE2DMULTISAMPLEPROC)wglGetProcAddress             ("glTexImage2DMultisample"                                    );
     706             :                 glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)wglGetProcAddress ("glRenderbufferStorageMultisample"     );
     707             :                 glBlitFramebuffer                       = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress                   ("glBlitFramebuffer"                  );
     708             :                 glClampColor                            = (PFNGLCLAMPCOLORPROC)wglGetProcAddress                                ("glClampColor"                                       );
     709             :         }
     710             : #endif
     711             : }
     712             : #endif
     713             : 
     714             : 
     715             : #if OO_MULTITEXTURE
     716             : - (void)checkTextureCombinersSupported
     717             : {
     718             :         textureCombinersSupported = [self haveExtension:@"GL_ARB_texture_env_combine"];
     719             :         
     720             :         if (textureCombinersSupported)
     721             :         {
     722             :                 OOGL(glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &textureUnitCount));
     723             :                 
     724             : #if OOLITE_WINDOWS
     725             :                 // Duplicated in checkShadersSupported. but that's not really a problem.
     726             :                 glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
     727             :                 
     728             :                 glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC)wglGetProcAddress("glClientActiveTextureARB");
     729             : #endif
     730             :         }
     731             :         else
     732             :         {
     733             :                 textureUnitCount = 1;
     734             :         }
     735             : 
     736             : }
     737             : #endif
     738             : 
     739             : 
     740             : // regexps may be a single string or an array of strings (in which case results are ANDed).
     741           0 : static BOOL CheckRegExps(NSString *string, id regexps)
     742             : {
     743             :         if (regexps == nil)  return YES;        // No restriction == match.
     744             :         if ([regexps isKindOfClass:[NSString class]])
     745             :         {
     746             :                 return [string oo_matchesRegularExpression:regexps];
     747             :         }
     748             :         if ([regexps isKindOfClass:[NSArray class]])
     749             :         {
     750             :                 NSEnumerator *regexpEnum = nil;
     751             :                 NSString *regexp = nil;
     752             :                 
     753             :                 for (regexpEnum = [regexps objectEnumerator]; (regexp = [regexpEnum nextObject]); )
     754             :                 {
     755             :                         if (EXPECT_NOT(![regexp isKindOfClass:[NSString class]]))
     756             :                         {
     757             :                                 // Invalid type -- match fails.
     758             :                                 return NO;
     759             :                         }
     760             :                         
     761             :                         if (![string oo_matchesRegularExpression:regexp])  return NO;
     762             :                 }
     763             :                 return YES;
     764             :         }
     765             :         
     766             :         // Invalid type -- match fails.
     767             :         return NO;
     768             : }
     769             : 
     770             : 
     771           0 : NSComparisonResult CompareGPUSettingsByPriority(id a, id b, void *context)
     772             : {
     773             :         NSString                *keyA = a;
     774             :         NSString                *keyB = b;
     775             :         NSDictionary    *configurations = context;
     776             :         NSDictionary    *dictA = [configurations oo_dictionaryForKey:keyA];
     777             :         NSDictionary    *dictB = [configurations oo_dictionaryForKey:keyB];
     778             :         double                  precedenceA = [dictA oo_doubleForKey:@"precedence" defaultValue:1];
     779             :         double                  precedenceB = [dictB oo_doubleForKey:@"precedence" defaultValue:1];
     780             :         
     781             :         if (precedenceA > precedenceB)  return NSOrderedAscending;
     782             :         if (precedenceA < precedenceB)  return NSOrderedDescending;
     783             :         
     784             :         return [keyA caseInsensitiveCompare:keyB];
     785             : }
     786             : 
     787             : 
     788             : - (NSDictionary *) lookUpPerGPUSettingsWithVersionString:(NSString *)versionStr extensionsString:(NSString *)extensionsStr
     789             : {
     790             :         NSDictionary *configurations = [ResourceManager dictionaryFromFilesNamed:@"gpu-settings.plist"
     791             :                                                                                                                                         inFolder:@"Config"
     792             :                                                                                                                                         andMerge:YES];
     793             :         
     794             :         NSArray *keys = [[configurations allKeys] sortedArrayUsingFunction:CompareGPUSettingsByPriority context:configurations];
     795             :         
     796             :         NSEnumerator *keyEnum = nil;
     797             :         NSString *key = nil;
     798             :         NSDictionary *config = nil;
     799             :         
     800             :         for (keyEnum = [keys objectEnumerator]; (key = [keyEnum nextObject]); )
     801             :         {
     802             :                 config = [configurations oo_dictionaryForKey:key];
     803             :                 if (EXPECT_NOT(config == nil))  continue;
     804             :                 
     805             :                 NSDictionary *match = [config oo_dictionaryForKey:@"match"];
     806             :                 NSString *expr = nil;
     807             :                 
     808             :                 expr = [match objectForKey:@"vendor"];
     809             :                 if (!CheckRegExps(vendor, expr))  continue;
     810             :                 
     811             :                 expr = [match oo_stringForKey:@"renderer"];
     812             :                 if (!CheckRegExps(renderer, expr))  continue;
     813             :                 
     814             :                 expr = [match oo_stringForKey:@"version"];
     815             :                 if (!CheckRegExps(versionStr, expr))  continue;
     816             :                 
     817             :                 expr = [match oo_stringForKey:@"extensions"];
     818             :                 if (!CheckRegExps(extensionsStr, expr))  continue;
     819             :                 
     820             :                 OOLog(@"rendering.opengl.gpuSpecific", @"Matched GPU configuration \"%@\".", key);
     821             :                 return config;
     822             :         }
     823             :         
     824             :         return [NSDictionary dictionary];
     825             : }
     826             : 
     827             : @end
     828             : 
     829             : 
     830             : @implementation OOOpenGLExtensionManager (Singleton)
     831             : 
     832             : /*      Canonical singleton boilerplate.
     833             :         See Cocoa Fundamentals Guide: Creating a Singleton Instance.
     834             :         See also +sharedManager above.
     835             :         
     836             :         // NOTE: assumes single-threaded first access.
     837             : */
     838             : 
     839           0 : + (id)allocWithZone:(NSZone *)inZone
     840             : {
     841             :         if (sSingleton == nil)
     842             :         {
     843             :                 sSingleton = [super allocWithZone:inZone];
     844             :                 return sSingleton;
     845             :         }
     846             :         return nil;
     847             : }
     848             : 
     849             : 
     850           0 : - (id)copyWithZone:(NSZone *)inZone
     851             : {
     852             :         return self;
     853             : }
     854             : 
     855             : 
     856           0 : - (id)retain
     857             : {
     858             :         return self;
     859             : }
     860             : 
     861             : 
     862           0 : - (NSUInteger)retainCount
     863             : {
     864             :         return UINT_MAX;
     865             : }
     866             : 
     867             : 
     868           0 : - (void)release
     869             : {}
     870             : 
     871             : 
     872           0 : - (id)autorelease
     873             : {
     874             :         return self;
     875             : }
     876             : 
     877             : @end
     878             : 
     879             : 
     880             : #if OOLITE_WINDOWS
     881             : 
     882             : static void OOBadOpenGLExtensionUsed(void)
     883             : {
     884             :         OOLog(@"rendering.opengl.badExtension", @"***** An uninitialized OpenGL extension function has been called, terminating. This is a serious error, please report it. *****");
     885             :         exit(EXIT_FAILURE);
     886             : }
     887             : 
     888             : #endif

Generated by: LCOV version 1.14