Oolite 1.91.0.7646-241128-10e222e
Loading...
Searching...
No Matches
OOTexture.m
Go to the documentation of this file.
1/*
2
3 OOTexture.m
4
5 Copyright (C) 2007-2013 Jens Ayton and contributors
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the Software is
12 furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 SOFTWARE.
24
25*/
26
27#import "OOTexture.h"
28#import "OOTextureInternal.h"
29#import "OOConcreteTexture.h"
30#import "OONullTexture.h"
31
32#import "OOTextureLoader.h"
34
36#import "Universe.h"
37#import "ResourceManager.h"
39#import "OOMacroOpenGL.h"
40#import "OOCPUInfo.h"
41#import "OOCache.h"
42#import "OOPixMap.h"
43
44
45NSString * const kOOTextureSpecifierNameKey = @"name";
46NSString * const kOOTextureSpecifierSwizzleKey = @"extract_channel";
47NSString * const kOOTextureSpecifierMinFilterKey = @"min_filter";
48NSString * const kOOTextureSpecifierMagFilterKey = @"mag_filter";
49NSString * const kOOTextureSpecifierNoShrinkKey = @"no_shrink";
50NSString * const kOOTextureSpecifierExtraShrinkKey = @"extra_shrink";
51NSString * const kOOTextureSpecifierRepeatSKey = @"repeat_s";
52NSString * const kOOTextureSpecifierRepeatTKey = @"repeat_t";
53NSString * const kOOTextureSpecifierCubeMapKey = @"cube_map";
54NSString * const kOOTextureSpecifierAnisotropyKey = @"anisotropy";
55NSString * const kOOTextureSpecifierLODBiasKey = @"texture_LOD_bias";
56
57NSString * const kOOTextureSpecifierModulateColorKey = @"color";
58NSString * const kOOTextureSpecifierIlluminationModeKey = @"illumination_mode";
59NSString * const kOOTextureSpecifierSelfColorKey = @"self_color";
60NSString * const kOOTextureSpecifierScaleFactorKey = @"scale_factor";
61NSString * const kOOTextureSpecifierBindingKey = @"binding";
62
63// Used only by "internal" specifiers from OOMakeTextureSpecifier.
64static NSString * const kOOTextureSpecifierFlagValueInternalKey = @"_oo_internal_flags";
65
66
67/* Texture caching:
68 two and a half parallel caching mechanisms are used. sLiveTextureCache
69 tracks all live texture objects with cache keys, without retaining them
70 (using NSValues to refer to the objects).
71
72 sAllLiveTextures tracks all textures, including ones without cache keys,
73 so that they can be notified of graphics resets. This also uses NSValues
74 to avoid retaining the textures.
75
76 sRecentTextures tracks up to kRecentTexturesCount textures which
77 have been used recently, and retains them.
78
79 This means that the number of live texture objects will never fall below
80 80% of kRecentTexturesCount (80% comes from the behaviour of OOCache), but
81 old textures will eventually be released. If the number of active textures
82 exceeds kRecentTexturesCount, all of them will be reusable through
83 sLiveTextureCache, but only a most-recently-fetched subset will be kept
84 around by the cache when the number drops.
85
86 Note the textures in sRecentTextures are a superset of the textures in
87 sLiveTextureCache, and the textures in sLiveTextureCache are a superset
88 of sRecentTextures.
89*/
90enum
91{
93};
94
95static NSMutableDictionary *sLiveTextureCache;
96static NSMutableSet *sAllLiveTextures;
98
99
102
103
104@interface OOTexture (OOPrivate)
105
106- (void) addToCaches;
107+ (OOTexture *) existingTextureForKey:(NSString *)key;
108
109- (void) forceRebind;
110
111+ (void)checkExtensions;
112
113#ifndef NDEBUG
114- (id) retainInContext:(NSString *)context;
115- (void) releaseInContext:(NSString *)context;
116- (id) autoreleaseInContext:(NSString *)context;
117#endif
118
119@end
121
122#ifndef NDEBUG
123static NSString *sGlobalTraceContext = nil;
124
125#define SET_TRACE_CONTEXT(str) do { sGlobalTraceContext = (str); } while (0)
126#else
127#define SET_TRACE_CONTEXT(str) do { } while (0)
128#endif
129#define CLEAR_TRACE_CONTEXT() SET_TRACE_CONTEXT(nil)
130
131
132@implementation OOTexture
133
134+ (id)textureWithName:(NSString *)name
135 inFolder:(NSString*)directory
136 options:(OOTextureFlags)options
137 anisotropy:(GLfloat)anisotropy
138 lodBias:(GLfloat)lodBias
139{
140 NSString *key = nil;
141 OOTexture *result = nil;
142 NSString *path = nil;
143 BOOL noFNF;
144
145 if (EXPECT_NOT(name == nil)) return nil;
146 if (EXPECT_NOT(!sCheckedExtensions)) [self checkExtensions];
147
149 {
150 anisotropy = 0.0f;
151 }
153 {
154 lodBias = 0.0f;
155 }
156
157 noFNF = (options & kOOTextureNoFNFMessage) != 0;
159
160 // Look for existing texture
161 key = OOGenerateTextureCacheKey(directory, name, options, anisotropy, lodBias);
162 result = [OOTexture existingTextureForKey:key];
163 if (result == nil)
164 {
165 path = [ResourceManager pathForFileNamed:name inFolder:directory];
166 if (path == nil)
167 {
168 if (!noFNF) OOLogWARN(kOOLogFileNotFound, @"Could not find texture file \"%@\".", name);
169 return nil;
170 }
171
172 // No existing texture, load texture.
173 result = [[[OOConcreteTexture alloc] initWithPath:path key:key options:options anisotropy:anisotropy lodBias:lodBias] autorelease];
174 }
175
176
177 return result;
178}
179
180
181+ (id)textureWithName:(NSString *)name
182 inFolder:(NSString*)directory
183{
184 return [self textureWithName:name
185 inFolder:directory
186 options:kOOTextureDefaultOptions
187 anisotropy:kOOTextureDefaultAnisotropy
188 lodBias:kOOTextureDefaultLODBias];
189}
190
191
192+ (id)textureWithConfiguration:(id)configuration
193{
194 return [self textureWithConfiguration:configuration extraOptions:0];
195}
196
197
198+ (id) textureWithConfiguration:(id)configuration extraOptions:(OOTextureFlags)extraOptions
199{
200 NSString *name = nil;
201 OOTextureFlags options = 0;
202 GLfloat anisotropy = 0.0f;
203 GLfloat lodBias = 0.0f;
204
205 if (!OOInterpretTextureSpecifier(configuration, &name, &options, &anisotropy, &lodBias, NO)) return nil;
206
207 return [self textureWithName:name inFolder:@"Textures" options:options | extraOptions anisotropy:anisotropy lodBias:lodBias];
208}
209
210
211+ (id) nullTexture
212{
214}
215
216
217+ (id) textureWithGenerator:(OOTextureGenerator *)generator
218{
219 return [self textureWithGenerator:generator enqueue: NO];
220}
221
222
223+ (id) textureWithGenerator:(OOTextureGenerator *)generator enqueue:(BOOL) enqueue
224{
225 if (generator == nil) return nil;
226
227#ifndef OOTEXTURE_NO_CACHE
228 OOTexture *existing = [OOTexture existingTextureForKey:[generator cacheKey]];
229 if (existing != nil && !enqueue) return [[existing retain] autorelease];
230#endif
231
232 if (![generator enqueue])
233 {
234 OOLogERR(@"texture.generator.queue.failed", @"Failed to queue generator %@", generator);
235 return nil;
236 }
237 OOLog(@"texture.generator.queue", @"Queued texture generator %@", generator);
238
239 OOTexture *result = [[[OOConcreteTexture alloc] initWithLoader:generator
240 key:[generator cacheKey]
241 options:OOApplyTextureOptionDefaults([generator textureOptions])
242 anisotropy:[generator anisotropy]
243 lodBias:[generator lodBias]] autorelease];
244
245 return result;
246}
247
248
249- (id) init
250{
251 if ((self = [super init]))
252 {
253 if (EXPECT_NOT(sAllLiveTextures == nil)) sAllLiveTextures = [[NSMutableSet alloc] init];
254 [sAllLiveTextures addObject:[NSValue valueWithPointer:self]];
255 }
256
257 return self;
258}
259
260
261- (void) dealloc
262{
263 [sAllLiveTextures removeObject:[NSValue valueWithPointer:self]];
264
265 [super dealloc];
266}
267
268
269- (void)apply
270{
272}
273
274
275+ (void)applyNone
276{
278 OOGL(glBindTexture(GL_TEXTURE_2D, 0));
279#if OO_TEXTURE_CUBE_MAP
280 if (OOCubeMapsAvailable()) OOGL(glBindTexture(GL_TEXTURE_CUBE_MAP, 0));
281#endif
282
283#if GL_EXT_texture_lod_bias
284 if (gOOTextureInfo.textureLODBiasAvailable) OOGL(glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0));
285#endif
286}
287
288
289- (void)ensureFinishedLoading
290{
291}
292
293
294- (BOOL) isFinishedLoading
295{
296 return YES;
297}
298
299
300- (NSString *) cacheKey
301{
302 return nil;
303}
304
305
306- (NSSize) dimensions
307{
309 return NSZeroSize;
310}
311
312
313- (NSSize) originalDimensions
314{
315 return [self dimensions];
316}
317
318
319- (BOOL) isMipMapped
320{
322 return NO;
323}
324
325
326- (struct OOPixMap) copyPixMapRepresentation
327{
328 return kOONullPixMap;
329}
330
331
332- (BOOL) isRectangleTexture
333{
334 return NO;
335}
336
337
338- (BOOL) isCubeMap
339{
340 return NO;
341}
342
343
344- (NSSize)texCoordsScale
345{
346 return NSMakeSize(1.0, 1.0);
347}
348
349
350- (GLint)glTextureName
351{
353 return 0;
354}
355
356
357+ (void)clearCache
358{
359 /* Does not clear sAllLiveTextures - that really must refer to all
360 live texture objects.
361 */
362 SET_TRACE_CONTEXT(@"clearing sLiveTextureCache");
363 [sLiveTextureCache autorelease];
365
366 SET_TRACE_CONTEXT(@"clearing sRecentTextures");
367 [sRecentTextures autorelease];
370}
371
372
373+ (void)rebindAllTextures
374{
375 NSEnumerator *textureEnum = nil;
376 id texture = nil;
377
378 // Keeping around unused, cached textures is unhelpful at this point.
380
381 for (textureEnum = [sAllLiveTextures objectEnumerator]; (texture = [[textureEnum nextObject] pointerValue]); )
382 {
383 [texture forceRebind];
384 }
385}
386
387
388#ifndef NDEBUG
389- (void) setTrace:(BOOL)trace
390{
391 if (trace && !_trace)
392 {
393 OOLog(@"texture.allocTrace.begin", @"Started tracing texture %p with retain count %lu.", self, [self retainCount]);
394 }
395 _trace = trace;
396}
397
398
399+ (NSArray *) cachedTexturesByAge
400{
401 return [sRecentTextures objectsByAge];
402}
403
404
405+ (NSSet *) allTextures
406{
407 NSMutableSet *result = [NSMutableSet setWithCapacity:[sAllLiveTextures count]];
408 NSValue *box = nil;
409 NSEnumerator *texEnum = nil;
410 for (texEnum = [sAllLiveTextures objectEnumerator]; (box = [texEnum nextObject]); )
411 {
412 [result addObject:[box pointerValue]];
413 }
414
415 return result;
416}
417
418
419- (size_t) dataSize
420{
421 NSSize dimensions = [self dimensions];
422 size_t size = dimensions.width * dimensions.height;
423 if ([self isCubeMap]) size *= 6;
424 if ([self isMipMapped]) size = size * 4 / 3;
425
426 return size;
427}
428
429
430- (NSString *) name
431{
433 return nil;
434}
435#endif
436
437
438- (void) forceRebind
439{
441}
442
443
444- (void) addToCaches
445{
446#ifndef OOTEXTURE_NO_CACHE
447 NSString *cacheKey = [self cacheKey];
448 if (cacheKey == nil) return;
449
450 // Add self to in-use textures cache, wrapped in an NSValue so the texture isn't retained by the cache.
451 if (EXPECT_NOT(sLiveTextureCache == nil)) sLiveTextureCache = [[NSMutableDictionary alloc] init];
452
453 SET_TRACE_CONTEXT(@"in-use textures cache - SHOULD NOT RETAIN");
454 [sLiveTextureCache setObject:[NSValue valueWithPointer:self] forKey:cacheKey];
456
457 // Add self to recent textures cache.
459 {
460 sRecentTextures = [[OOCache alloc] init];
461 [sRecentTextures setName:@"recent textures"];
462 [sRecentTextures setAutoPrune:YES];
463 [sRecentTextures setPruneThreshold:kRecentTexturesCount];
464 }
465
466 SET_TRACE_CONTEXT(@"adding to recent textures cache");
467 [sRecentTextures setObject:self forKey:cacheKey];
469#endif
470}
471
472
473- (void) removeFromCaches
474{
475#ifndef OOTEXTURE_NO_CACHE
476 NSString *cacheKey = [self cacheKey];
477 if (cacheKey == nil) return;
478
479 [sLiveTextureCache removeObjectForKey:cacheKey];
480 if (EXPECT_NOT([sRecentTextures objectForKey:cacheKey] == self))
481 {
482 /* Experimental for now: I think the recent crash problems may
483 * be because if the last reference to a texture is in
484 * sRecentTextures, and the texture is regenerated, it
485 * replaces the texture, causing a release. Therefore, if this
486 * texture *isn't* overretained in the texture cache, the 2009
487 * crash avoider will delete its replacement from the cache
488 * ... possibly before that texture has been fully added to
489 * the cache itself. So, the texture is only removed from the
490 * cache by key if it was in it with that key. The extra time
491 * needed to generate a planet texture compared with loading a
492 * standard one may be why this problem shows up. - CIM 20140122
493 */
494 NSAssert2(0, @"Texture retain count error for %@; cacheKey is %@.", self, cacheKey); //miscount in autorelease
495 // The following line is needed in order to avoid crashes when there's a 'texture retain count error'. Please do not delete. -- Kaks 20091221
496 [sRecentTextures removeObjectForKey:cacheKey]; // make sure there's no reference left inside sRecentTexture ( was a show stopper for 1.73)
497 }
498#endif
499}
500
501
502+ (OOTexture *) existingTextureForKey:(NSString *)key
503{
504#ifndef OOTEXTURE_NO_CACHE
505 if (key != nil)
506 {
507 return (OOTexture *)[[sLiveTextureCache objectForKey:key] pointerValue];
508 }
509 return nil;
510#else
511 return nil;
512#endif
513}
514
515
516+ (void)checkExtensions
517{
519
520 sCheckedExtensions = YES;
521
523 BOOL ver120 = [extMgr versionIsAtLeastMajor:1 minor:2];
524 BOOL ver130 = [extMgr versionIsAtLeastMajor:1 minor:3];
525
526#if GL_EXT_texture_filter_anisotropic
527 gOOTextureInfo.anisotropyAvailable = [extMgr haveExtension:@"GL_EXT_texture_filter_anisotropic"];
528 OOGL(glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gOOTextureInfo.anisotropyScale));
529 gOOTextureInfo.anisotropyScale *= OOClamp_0_1_f([[NSUserDefaults standardUserDefaults] oo_floatForKey:@"texture-anisotropy-scale" defaultValue:0.5]);
530#endif
531
532#ifdef GL_CLAMP_TO_EDGE
533 gOOTextureInfo.clampToEdgeAvailable = ver120 || [extMgr haveExtension:@"GL_SGIS_texture_edge_clamp"];
534#endif
535
536#if OO_GL_CLIENT_STORAGE
537 gOOTextureInfo.clientStorageAvailable = [extMgr haveExtension:@"GL_APPLE_client_storage"];
538#endif
539
540 gOOTextureInfo.textureMaxLevelAvailable = ver120 || [extMgr haveExtension:@"GL_SGIS_texture_lod"];
541
542#if GL_EXT_texture_lod_bias
543 if ([[NSUserDefaults standardUserDefaults] oo_boolForKey:@"use-texture-lod-bias" defaultValue:YES])
544 {
545 gOOTextureInfo.textureLODBiasAvailable = [extMgr haveExtension:@"GL_EXT_texture_lod_bias"];
546 }
547 else
548 {
550 }
551#endif
552
553#if GL_EXT_texture_rectangle
554 gOOTextureInfo.rectangleTextureAvailable = [extMgr haveExtension:@"GL_EXT_texture_rectangle"];
555#endif
556
557#if OO_TEXTURE_CUBE_MAP
558 if (![[NSUserDefaults standardUserDefaults] boolForKey:@"disable-cube-maps"])
559 {
560 gOOTextureInfo.cubeMapAvailable = ver130 || [extMgr haveExtension:@"GL_ARB_texture_cube_map"];
561 }
562 else
563 {
565 }
566
567#endif
568}
569
570
571#ifndef NDEBUG
572- (id) retainInContext:(NSString *)context
573{
574 if (_trace)
575 {
576 if (context) OOLog(@"texture.allocTrace.retain", @"Texture %p retained (retain count -> %lu) - %@.", self, [self retainCount] + 1, context);
577 else OOLog(@"texture.allocTrace.retain", @"Texture %p retained (retain count -> %lu).", self, [self retainCount] + 1);
578 }
579
580 return [super retain];
581}
582
583
584- (void) releaseInContext:(NSString *)context
585{
586 if (_trace)
587 {
588 if (context) OOLog(@"texture.allocTrace.release", @"Texture %p released (retain count -> %lu) - %@.", self, [self retainCount] - 1, context);
589 else OOLog(@"texture.allocTrace.release", @"Texture %p released (retain count -> %lu).", self, [self retainCount] - 1);
590 }
591
592 [super release];
593}
594
595
596- (id) autoreleaseInContext:(NSString *)context
597{
598 if (_trace)
599 {
600 if (context) OOLog(@"texture.allocTrace.autoreleased", @"Texture %p autoreleased - %@.", self, context);
601 else OOLog(@"texture.allocTrace.autoreleased", @"Texture %p autoreleased.", self);
602 }
603
604 return [super autorelease];
605}
606
607
608- (id) retain
609{
610 return [self retainInContext:sGlobalTraceContext];
611}
612
613
614- (oneway void) release
615{
616 [self releaseInContext:sGlobalTraceContext];
617}
618
619
620- (id) autorelease
621{
622 return [self autoreleaseInContext:sGlobalTraceContext];
623}
624#endif
625
626@end
627
628
629@implementation NSDictionary (OOTextureConveniences)
630
631- (NSDictionary *) oo_textureSpecifierForKey:(id)key defaultName:(NSString *)name
632{
633 return OOTextureSpecFromObject([self objectForKey:key], name);
634}
635
636@end
637
638@implementation NSArray (OOTextureConveniences)
639
640- (NSDictionary *) oo_textureSpecifierAtIndex:(unsigned)index defaultName:(NSString *)name
641{
642 return OOTextureSpecFromObject([self objectAtIndex:index], name);
643}
644
645@end
646
647NSDictionary *OOTextureSpecFromObject(id object, NSString *defaultName)
648{
649 if (object == nil) object = defaultName;
650 if ([object isKindOfClass:[NSString class]])
651 {
652 if ([object isEqualToString:@""]) return nil;
653 return [NSDictionary dictionaryWithObject:object forKey:@"name"];
654 }
655 if (![object isKindOfClass:[NSDictionary class]]) return nil;
656
657 // If we're here, it's a dictionary.
658 if (defaultName == nil || [object oo_stringForKey:@"name"] != nil) return object;
659
660 // If we get here, there's no "name" key and there is a default, so we fill it in:
661 NSMutableDictionary *mutableResult = [NSMutableDictionary dictionaryWithDictionary:object];
662 [mutableResult setObject:[[defaultName copy] autorelease] forKey:@"name"];
663 return mutableResult;
664}
665
666
668{
669 switch (format)
670 {
672 return 4;
673
675 return 1;
676
678 return 2;
679
681 break;
682 }
683
684 return 0;
685}
686
687
689{
691}
692
693
694BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, OOTextureFlags *outOptions, float *outAnisotropy, float *outLODBias, BOOL ignoreExtract)
695{
696 NSString *name = nil;
698 float anisotropy = kOOTextureDefaultAnisotropy;
699 float lodBias = kOOTextureDefaultLODBias;
700
701 if ([specifier isKindOfClass:[NSString class]])
702 {
703 name = specifier;
704 }
705 else if ([specifier isKindOfClass:[NSDictionary class]])
706 {
707 name = [specifier oo_stringForKey:kOOTextureSpecifierNameKey];
708 if (name == nil)
709 {
710 OOLog(@"texture.load.noName", @"Invalid texture configuration dictionary (must specify name):\n%@", specifier);
711 return NO;
712 }
713
714 int quickFlags = [specifier oo_intForKey:kOOTextureSpecifierFlagValueInternalKey defaultValue:-1];
715 if (quickFlags != -1)
716 {
717 options = quickFlags;
718 }
719 else
720 {
721 NSString *filterString = [specifier oo_stringForKey:kOOTextureSpecifierMinFilterKey defaultValue:@"default"];
722 if ([filterString isEqualToString:@"nearest"]) options |= kOOTextureMinFilterNearest;
723 else if ([filterString isEqualToString:@"linear"]) options |= kOOTextureMinFilterLinear;
724 else if ([filterString isEqualToString:@"mipmap"]) options |= kOOTextureMinFilterMipMap;
725 else options |= kOOTextureMinFilterDefault; // Covers "default"
726
727 filterString = [specifier oo_stringForKey:kOOTextureSpecifierMagFilterKey defaultValue:@"default"];
728 if ([filterString isEqualToString:@"nearest"]) options |= kOOTextureMagFilterNearest;
729 else options |= kOOTextureMagFilterLinear; // Covers "default" and "linear"
730
731 if ([specifier oo_boolForKey:kOOTextureSpecifierNoShrinkKey defaultValue:NO]) options |= kOOTextureNoShrink;
732 if ([specifier oo_boolForKey:kOOTextureSpecifierExtraShrinkKey defaultValue:NO]) options |= kOOTextureExtraShrink;
733 if ([specifier oo_boolForKey:kOOTextureSpecifierRepeatSKey defaultValue:NO]) options |= kOOTextureRepeatS;
734 if ([specifier oo_boolForKey:kOOTextureSpecifierRepeatTKey defaultValue:NO]) options |= kOOTextureRepeatT;
735 if ([specifier oo_boolForKey:kOOTextureSpecifierCubeMapKey defaultValue:NO]) options |= kOOTextureAllowCubeMap;
736
737 if (!ignoreExtract)
738 {
739 NSString *extractChannel = [specifier oo_stringForKey:@"extract_channel"];
740 if (extractChannel != nil)
741 {
742 if ([extractChannel isEqualToString:@"r"]) options |= kOOTextureExtractChannelR;
743 else if ([extractChannel isEqualToString:@"g"]) options |= kOOTextureExtractChannelG;
744 else if ([extractChannel isEqualToString:@"b"]) options |= kOOTextureExtractChannelB;
745 else if ([extractChannel isEqualToString:@"a"]) options |= kOOTextureExtractChannelA;
746 else
747 {
748 OOLogWARN(@"texture.load.extractChannel.invalid", @"Unknown value \"%@\" for extract_channel in specifier \"%@\" (should be \"r\", \"g\", \"b\" or \"a\").", extractChannel,specifier);
749 }
750 }
751 }
752 }
753 anisotropy = [specifier oo_floatForKey:@"anisotropy" defaultValue:kOOTextureDefaultAnisotropy];
754 lodBias = [specifier oo_floatForKey:@"texture_LOD_bias" defaultValue:kOOTextureDefaultLODBias];
755 }
756 else
757 {
758 // Bad type
759 if (specifier != nil) OOLog(kOOLogParameterError, @"%s: expected string or dictionary, got %@.", __PRETTY_FUNCTION__, [specifier class]);
760 return NO;
761 }
762
763 if ([name length] == 0) return NO;
764
765 if (outName != NULL) *outName = name;
766 if (outOptions != NULL) *outOptions = options;
767 if (outAnisotropy != NULL) *outAnisotropy = anisotropy;
768 if (outLODBias != NULL) *outLODBias = lodBias;
769
770 return YES;
771}
772
773
774NSDictionary *OOMakeTextureSpecifier(NSString *name, OOTextureFlags options, float anisotropy, float lodBias, BOOL internal)
775{
776 NSMutableDictionary *result = [NSMutableDictionary dictionary];
777
778 [result setObject:name forKey:kOOTextureSpecifierNameKey];
779
780 if (anisotropy != kOOTextureDefaultAnisotropy) [result oo_setFloat:anisotropy forKey:kOOTextureSpecifierAnisotropyKey];
781 if (lodBias != kOOTextureDefaultLODBias) [result oo_setFloat:lodBias forKey:kOOTextureSpecifierLODBiasKey];
782
783 if (internal)
784 {
785 [result oo_setUnsignedInteger:options forKey:kOOTextureSpecifierFlagValueInternalKey];
786 }
787 else
788 {
789 NSString *value = nil;
790 switch (options & kOOTextureMinFilterMask)
791 {
793 break;
794
796 value = @"nearest";
797 break;
798
800 value = @"linear";
801 break;
802
804 value = @"mipmap";
805 break;
806 }
807 if (value != nil) [result setObject:value forKey:kOOTextureSpecifierNoShrinkKey];
808
809 value = nil;
810 switch (options & kOOTextureMagFilterMask)
811 {
813 value = @"nearest";
814 break;
815
817 break;
818 }
819 if (value != nil) [result setObject:value forKey:kOOTextureSpecifierMagFilterKey];
820
821 value = nil;
822 switch (options & kOOTextureExtractChannelMask)
823 {
825 break;
826
828 value = @"r";
829 break;
830
832 value = @"g";
833 break;
834
836 value = @"b";
837 break;
838
840 value = @"a";
841 break;
842 }
843 if (value != nil) [result setObject:value forKey:kOOTextureSpecifierSwizzleKey];
844
845 if (options & kOOTextureNoShrink) [result oo_setBool:YES forKey:kOOTextureSpecifierNoShrinkKey];
846 if (options & kOOTextureRepeatS) [result oo_setBool:YES forKey:kOOTextureSpecifierRepeatSKey];
847 if (options & kOOTextureRepeatT) [result oo_setBool:YES forKey:kOOTextureSpecifierRepeatTKey];
848 if (options & kOOTextureAllowCubeMap) [result oo_setBool:YES forKey:kOOTextureSpecifierCubeMapKey];
849 }
850
851 return result;
852}
853
854
856{
857 // Set default flags if needed
859 {
860 if ([UNIVERSE reducedDetail])
861 {
862 options |= kOOTextureMinFilterLinear;
863 }
864 else
865 {
866 options |= kOOTextureMinFilterMipMap;
867 }
868 }
869
871 {
872 /* In the unlikely case of an OpenGL system without GL_SGIS_texture_lod,
873 disable mip-mapping completely. Strictly this is only needed for
874 non-square textures, but extra logic for such a rare case isn't
875 worth it.
876 */
878 {
880 }
881 }
882
883 if (options & kOOTextureAllowRectTexture)
884 {
885 // Apply rectangle texture restrictions (regardless of whether rectangle textures are available, for consistency)
888 {
889 options = (kOOTextureMinFilterMask & ~kOOTextureMinFilterMask) | kOOTextureMinFilterLinear;
890 }
891
892#if GL_EXT_texture_rectangle
894 {
895 options &= ~kOOTextureAllowRectTexture;
896 }
897#else
898 options &= ~kOOTextureAllowRectTexture;
899#endif
900 }
901
902 options &= kOOTextureDefinedFlags;
903
904 return options;
905}
906
907
908NSString *OOGenerateTextureCacheKey(NSString *directory, NSString *name, OOTextureFlags options, float anisotropy, float lodBias)
909{
911 {
912 anisotropy = 0.0f;
913 }
915 {
916 lodBias = 0.0f;
917 }
919
920 return [NSString stringWithFormat:@"%@%@%@:0x%.4X/%g/%g", directory ? directory : (NSString *)@"", directory ? @"/" : @"", name, options, anisotropy, lodBias];
921}
922
923
924NSString *OOTextureCacheKeyForSpecifier(id specifier)
925{
926 NSString *name;
927 OOTextureFlags options;
928 float anisotropy;
929 float lodBias;
930
931 OOInterpretTextureSpecifier(specifier, &name, &options, &anisotropy, &lodBias, NO);
932 return OOGenerateTextureCacheKey(@"Textures", name, options, anisotropy, lodBias);
933}
#define DESTROY(x)
Definition OOCocoa.h:77
#define EXPECT_NOT(x)
#define OOLogWARN(class, format,...)
Definition OOLogging.h:113
#define OOLogERR(class, format,...)
Definition OOLogging.h:112
#define OOLogGenericSubclassResponsibility()
Definition OOLogging.h:129
#define OOLog(class, format,...)
Definition OOLogging.h:88
NSString *const kOOLogParameterError
Definition OOLogging.m:647
NSString *const kOOLogFileNotFound
Definition OOLogging.m:652
#define OO_ENTER_OPENGL()
#define OOGL(statement)
Definition OOOpenGL.h:251
OOPixMapFormat
Definition OOPixMap.h:39
const OOPixMap kOONullPixMap
Definition OOPixMap.m:31
return nil
NSString *const kOOTextureSpecifierNoShrinkKey
Definition OOTexture.m:49
BOOL OOCubeMapsAvailable(void)
Definition OOTexture.m:688
uint8_t OOTextureComponentsForFormat(OOTextureDataFormat format)
Definition OOTexture.m:667
@ kOOTextureDataGrayscaleAlpha
Definition OOTexture.h:111
@ kOOTextureDataGrayscale
Definition OOTexture.h:110
@ kOOTextureDataInvalid
Definition OOTexture.h:107
@ kOOTextureDataRGBA
Definition OOTexture.h:109
NSDictionary * OOMakeTextureSpecifier(NSString *name, OOTextureFlags options, float anisotropy, float lodBias, BOOL internal)
Definition OOTexture.m:774
NSString *const kOOTextureSpecifierRepeatTKey
Definition OOTexture.m:52
OOTextureFlags OOApplyTextureOptionDefaults(OOTextureFlags options)
Definition OOTexture.m:855
NSDictionary * OOTextureSpecFromObject(id object, NSString *defaultName)
Definition OOTexture.m:647
#define kOOTextureDefaultAnisotropy
Definition OOTexture.h:101
@ kOOTextureRepeatS
Definition OOTexture.h:55
@ kOOTextureAllowRectTexture
Definition OOTexture.h:57
@ kOOTextureExtractChannelA
Definition OOTexture.h:70
@ kOOTextureExtractChannelB
Definition OOTexture.h:69
@ kOOTextureNoFNFMessage
Definition OOTexture.h:58
@ kOOTextureNoShrink
Definition OOTexture.h:53
@ kOOTextureMinFilterDefault
Definition OOTexture.h:45
@ kOOTextureExtractChannelNone
Definition OOTexture.h:66
@ kOOTextureMagFilterMask
Definition OOTexture.h:73
@ kOOTextureExtractChannelMask
Definition OOTexture.h:65
@ kOOTextureDefinedFlags
Definition OOTexture.h:78
@ kOOTextureMinFilterLinear
Definition OOTexture.h:47
@ kOOTextureAllowCubeMap
Definition OOTexture.h:61
@ kOOTextureMinFilterMask
Definition OOTexture.h:72
@ kOOTextureRepeatT
Definition OOTexture.h:56
@ kOOTextureDefaultOptions
Definition OOTexture.h:76
@ kOOTextureMinFilterMipMap
Definition OOTexture.h:48
@ kOOTextureMagFilterNearest
Definition OOTexture.h:50
@ kOOTextureExtraShrink
Definition OOTexture.h:54
@ kOOTextureExtractChannelG
Definition OOTexture.h:68
@ kOOTextureFlagsAllowedForRectangleTexture
Definition OOTexture.h:91
@ kOOTextureExtractChannelR
Definition OOTexture.h:67
@ kOOTextureMagFilterLinear
Definition OOTexture.h:51
@ kOOTextureMinFilterNearest
Definition OOTexture.h:46
uint32_t OOTextureFlags
Definition OOTexture.h:98
NSString *const kOOTextureSpecifierRepeatSKey
Definition OOTexture.m:51
#define kOOTextureDefaultLODBias
Definition OOTexture.h:102
BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, OOTextureFlags *outOptions, float *outAnisotropy, float *outLODBias, BOOL ignoreExtract)
Definition OOTexture.m:694
NSString *const kOOTextureSpecifierCubeMapKey
Definition OOTexture.m:53
NSString *const kOOTextureSpecifierExtraShrinkKey
Definition OOTexture.m:50
#define CLEAR_TRACE_CONTEXT()
Definition OOTexture.m:129
NSString *const kOOTextureSpecifierSelfColorKey
Definition OOTexture.m:59
NSString *const kOOTextureSpecifierNoShrinkKey
Definition OOTexture.m:49
NSString *const kOOTextureSpecifierNameKey
Definition OOTexture.m:45
#define SET_TRACE_CONTEXT(str)
Definition OOTexture.m:125
static OOCache * sRecentTextures
Definition OOTexture.m:97
NSString *const kOOTextureSpecifierRepeatTKey
Definition OOTexture.m:52
static NSMutableDictionary * sLiveTextureCache
Definition OOTexture.m:95
NSString *const kOOTextureSpecifierScaleFactorKey
Definition OOTexture.m:60
static NSString * sGlobalTraceContext
Definition OOTexture.m:123
NSString * OOTextureCacheKeyForSpecifier(id specifier)
Definition OOTexture.m:924
static BOOL sCheckedExtensions
Definition OOTexture.m:100
NSString *const kOOTextureSpecifierBindingKey
Definition OOTexture.m:61
static NSMutableSet * sAllLiveTextures
Definition OOTexture.m:96
NSString *const kOOTextureSpecifierIlluminationModeKey
Definition OOTexture.m:58
NSString *const kOOTextureSpecifierMinFilterKey
Definition OOTexture.m:47
NSString *const kOOTextureSpecifierMagFilterKey
Definition OOTexture.m:48
@ kRecentTexturesCount
Definition OOTexture.m:92
NSString *const kOOTextureSpecifierAnisotropyKey
Definition OOTexture.m:54
static NSString *const kOOTextureSpecifierFlagValueInternalKey
Definition OOTexture.m:64
NSString *const kOOTextureSpecifierRepeatSKey
Definition OOTexture.m:51
NSString * OOGenerateTextureCacheKey(NSString *directory, NSString *name, OOTextureFlags options, float anisotropy, float lodBias)
Definition OOTexture.m:908
NSString *const kOOTextureSpecifierModulateColorKey
Definition OOTexture.m:57
NSString *const kOOTextureSpecifierCubeMapKey
Definition OOTexture.m:53
OOTextureInfo gOOTextureInfo
Definition OOTexture.m:101
NSString *const kOOTextureSpecifierSwizzleKey
Definition OOTexture.m:46
NSString *const kOOTextureSpecifierExtraShrinkKey
Definition OOTexture.m:50
NSString *const kOOTextureSpecifierLODBiasKey
Definition OOTexture.m:55
#define UNIVERSE
Definition Universe.h:840
void setPruneThreshold:(unsigned threshold)
Definition OOCache.m:272
void setName:(NSString *name)
Definition OOCache.m:348
NSArray * objectsByAge()
Definition OOCache.m:354
void setAutoPrune:(BOOL flag)
Definition OOCache.m:289
void removeObjectForKey:(id key)
Definition OOCache.m:262
void setObject:forKey:(id value,[forKey] id key)
Definition OOCache.m:248
OONullTexture * sharedNullTexture()
BOOL versionIsAtLeastMajor:minor:(unsigned maj,[minor] unsigned min)
OOOpenGLExtensionManager * sharedManager()
BOOL haveExtension:(NSString *extension)
OOTexture * existingTextureForKey:(NSString *key)
Definition OOTexture.m:502
NSString * pathForFileNamed:inFolder:(NSString *fileName,[inFolder] NSString *folderName)
voidpf void uLong size
Definition ioapi.h:134
unsigned clientStorageAvailable
unsigned textureMaxLevelAvailable
unsigned anisotropyAvailable
unsigned clampToEdgeAvailable
unsigned cubeMapAvailable
unsigned rectangleTextureAvailable
unsigned textureLODBiasAvailable