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