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

          Line data    Source code
       1           0 : /*
       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"
      33             : #import "OOTextureGenerator.h"
      34             : 
      35             : #import "OOCollectionExtractors.h"
      36             : #import "Universe.h"
      37             : #import "ResourceManager.h"
      38             : #import "OOOpenGLExtensionManager.h"
      39             : #import "OOMacroOpenGL.h"
      40             : #import "OOCPUInfo.h"
      41             : #import "OOCache.h"
      42             : #import "OOPixMap.h"
      43             : 
      44             : 
      45           0 : NSString * const kOOTextureSpecifierNameKey                                     = @"name";
      46           0 : NSString * const kOOTextureSpecifierSwizzleKey                          = @"extract_channel";
      47           0 : NSString * const kOOTextureSpecifierMinFilterKey                        = @"min_filter";
      48           0 : NSString * const kOOTextureSpecifierMagFilterKey                        = @"mag_filter";
      49           0 : NSString * const kOOTextureSpecifierNoShrinkKey                         = @"no_shrink";
      50           0 : NSString * const kOOTextureSpecifierExtraShrinkKey                      = @"extra_shrink";
      51           0 : NSString * const kOOTextureSpecifierRepeatSKey                          = @"repeat_s";
      52           0 : NSString * const kOOTextureSpecifierRepeatTKey                          = @"repeat_t";
      53           0 : NSString * const kOOTextureSpecifierCubeMapKey                          = @"cube_map";
      54           0 : NSString * const kOOTextureSpecifierAnisotropyKey                       = @"anisotropy";
      55           0 : NSString * const kOOTextureSpecifierLODBiasKey                          = @"texture_LOD_bias";
      56             : 
      57           0 : NSString * const kOOTextureSpecifierModulateColorKey            = @"color";
      58           0 : NSString * const kOOTextureSpecifierIlluminationModeKey         = @"illumination_mode";
      59           0 : NSString * const kOOTextureSpecifierSelfColorKey                        = @"self_color";
      60           0 : NSString * const kOOTextureSpecifierScaleFactorKey                      = @"scale_factor";
      61           0 : NSString * const kOOTextureSpecifierBindingKey                          = @"binding";
      62             : 
      63             : // Used only by "internal" specifiers from OOMakeTextureSpecifier.
      64           0 : static 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             : */
      90           0 : enum
      91             : {
      92             :         kRecentTexturesCount            = 50
      93             : };
      94             : 
      95           0 : static NSMutableDictionary      *sLiveTextureCache;
      96           0 : static NSMutableSet                     *sAllLiveTextures;
      97           0 : static OOCache                          *sRecentTextures;
      98             : 
      99             : 
     100           0 : static BOOL                                     sCheckedExtensions;
     101           0 : OOTextureInfo                           gOOTextureInfo;
     102             : 
     103             : 
     104             : @interface OOTexture (OOPrivate)
     105             : 
     106           0 : - (void) addToCaches;
     107           0 : + (OOTexture *) existingTextureForKey:(NSString *)key;
     108             : 
     109           0 : - (void) forceRebind;
     110             : 
     111           0 : + (void)checkExtensions;
     112             : 
     113             : #ifndef NDEBUG
     114           0 : - (id) retainInContext:(NSString *)context;
     115           0 : - (void) releaseInContext:(NSString *)context;
     116           0 : - (id) autoreleaseInContext:(NSString *)context;
     117             : #endif
     118             : 
     119             : @end
     120             : 
     121             : 
     122             : #ifndef NDEBUG
     123           0 : static NSString *sGlobalTraceContext = nil;
     124             : 
     125           0 : #define SET_TRACE_CONTEXT(str) do { sGlobalTraceContext = (str); } while (0)
     126             : #else
     127             : #define SET_TRACE_CONTEXT(str) do { } while (0)
     128             : #endif
     129           0 : #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             :         
     148             :         if (!gOOTextureInfo.anisotropyAvailable || (options & kOOTextureMinFilterMask) != kOOTextureMinFilterMipMap)
     149             :         {
     150             :                 anisotropy = 0.0f;
     151             :         }
     152             :         if (!gOOTextureInfo.textureLODBiasAvailable || (options & kOOTextureMinFilterMask) != kOOTextureMinFilterMipMap)
     153             :         {
     154             :                 lodBias = 0.0f;
     155             :         }
     156             :         
     157             :         noFNF = (options & kOOTextureNoFNFMessage) != 0;
     158             :         options = OOApplyTextureOptionDefaults(options & ~kOOTextureNoFNFMessage);
     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             : {
     213             :         return [OONullTexture sharedNullTexture];
     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           0 : - (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           0 : - (void) dealloc
     262             : {
     263             :         [sAllLiveTextures removeObject:[NSValue valueWithPointer:self]];
     264             :         
     265             :         [super dealloc];
     266             : }
     267             : 
     268             : 
     269             : - (void)apply
     270             : {
     271             :         OOLogGenericSubclassResponsibility();
     272             : }
     273             : 
     274             : 
     275             : + (void)applyNone
     276             : {
     277             :         OO_ENTER_OPENGL();
     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             : {
     308             :         OOLogGenericSubclassResponsibility();
     309             :         return NSZeroSize;
     310             : }
     311             : 
     312             : 
     313             : - (NSSize) originalDimensions
     314             : {
     315             :         return [self dimensions];
     316             : }
     317             : 
     318             : 
     319             : - (BOOL) isMipMapped
     320             : {
     321             :         OOLogGenericSubclassResponsibility();
     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             : {
     352             :         OOLogGenericSubclassResponsibility();
     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];
     364             :         sLiveTextureCache = nil;
     365             :         
     366             :         SET_TRACE_CONTEXT(@"clearing sRecentTextures");
     367             :         [sRecentTextures autorelease];
     368             :         sRecentTextures = nil;
     369             :         CLEAR_TRACE_CONTEXT();
     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.
     379             :         DESTROY(sRecentTextures);
     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             : {
     432             :         OOLogGenericSubclassResponsibility();
     433             :         return nil;
     434             : }
     435             : #endif
     436             : 
     437             : 
     438           0 : - (void) forceRebind
     439             : {
     440             :         OOLogGenericSubclassResponsibility();
     441             : }
     442             : 
     443             : 
     444           0 : - (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];
     455             :         CLEAR_TRACE_CONTEXT();
     456             :         
     457             :         // Add self to recent textures cache.
     458             :         if (EXPECT_NOT(sRecentTextures == nil))
     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];
     468             :         CLEAR_TRACE_CONTEXT();
     469             : #endif
     470             : }
     471             : 
     472             : 
     473           0 : - (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           0 : + (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           0 : + (void)checkExtensions
     517             : {
     518             :         OO_ENTER_OPENGL();
     519             :         
     520             :         sCheckedExtensions = YES;
     521             :         
     522             :         OOOpenGLExtensionManager        *extMgr = [OOOpenGLExtensionManager sharedManager];
     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             :         {
     549             :                 gOOTextureInfo.textureLODBiasAvailable = NO;
     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             :         {
     564             :                 gOOTextureInfo.cubeMapAvailable = NO;
     565             :         }
     566             : 
     567             : #endif
     568             : }
     569             : 
     570             : 
     571             : #ifndef NDEBUG
     572           0 : - (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           0 : - (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           0 : - (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           0 : - (id) retain
     609             : {
     610             :         return [self retainInContext:sGlobalTraceContext];
     611             : }
     612             : 
     613             : 
     614           0 : - (oneway void) release
     615             : {
     616             :         [self releaseInContext:sGlobalTraceContext];
     617             : }
     618             : 
     619             : 
     620           0 : - (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             : 
     647           0 : NSDictionary *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             : 
     667           0 : uint8_t OOTextureComponentsForFormat(OOTextureDataFormat format)
     668             : {
     669             :         switch (format)
     670             :         {
     671             :                 case kOOTextureDataRGBA:
     672             :                         return 4;
     673             :                         
     674             :                 case kOOTextureDataGrayscale:
     675             :                         return 1;
     676             :                         
     677             :                 case kOOTextureDataGrayscaleAlpha:
     678             :                         return 2;
     679             :                         
     680             :                 case kOOTextureDataInvalid:
     681             :                         break;
     682             :         }
     683             :         
     684             :         return 0;
     685             : }
     686             : 
     687             : 
     688           0 : BOOL OOCubeMapsAvailable(void)
     689             : {
     690             :         return gOOTextureInfo.cubeMapAvailable;
     691             : }
     692             : 
     693             : 
     694           0 : BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, OOTextureFlags *outOptions, float *outAnisotropy, float *outLODBias, BOOL ignoreExtract)
     695             : {
     696             :         NSString                        *name = nil;
     697             :         OOTextureFlags          options = kOOTextureDefaultOptions;
     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             : 
     774           0 : NSDictionary *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             :                 {
     792             :                         case kOOTextureMinFilterDefault:
     793             :                                 break;
     794             :                                 
     795             :                         case kOOTextureMinFilterNearest:
     796             :                                 value = @"nearest";
     797             :                                 break;
     798             :                                 
     799             :                         case kOOTextureMinFilterLinear:
     800             :                                 value = @"linear";
     801             :                                 break;
     802             :                                 
     803             :                         case kOOTextureMinFilterMipMap:
     804             :                                 value = @"mipmap";
     805             :                                 break;
     806             :                 }
     807             :                 if (value != nil)  [result setObject:value forKey:kOOTextureSpecifierNoShrinkKey];
     808             :                 
     809             :                 value = nil;
     810             :                 switch (options & kOOTextureMagFilterMask)
     811             :                 {
     812             :                         case kOOTextureMagFilterNearest:
     813             :                                 value = @"nearest";
     814             :                                 break;
     815             :                                 
     816             :                         case kOOTextureMagFilterLinear:
     817             :                                 break;
     818             :                 }
     819             :                 if (value != nil)  [result setObject:value forKey:kOOTextureSpecifierMagFilterKey];
     820             :                 
     821             :                 value = nil;
     822             :                 switch (options & kOOTextureExtractChannelMask)
     823             :                 {
     824             :                         case kOOTextureExtractChannelNone:
     825             :                                 break;
     826             :                                 
     827             :                         case kOOTextureExtractChannelR:
     828             :                                 value = @"r";
     829             :                                 break;
     830             :                                 
     831             :                         case kOOTextureExtractChannelG:
     832             :                                 value = @"g";
     833             :                                 break;
     834             :                                 
     835             :                         case kOOTextureExtractChannelB:
     836             :                                 value = @"b";
     837             :                                 break;
     838             :                                 
     839             :                         case kOOTextureExtractChannelA:
     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             : 
     855           0 : OOTextureFlags OOApplyTextureOptionDefaults(OOTextureFlags options)
     856             : {
     857             :         // Set default flags if needed
     858             :         if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterDefault)
     859             :         {
     860             :                 if ([UNIVERSE reducedDetail])
     861             :                 {
     862             :                         options |= kOOTextureMinFilterLinear;
     863             :                 }
     864             :                 else
     865             :                 {
     866             :                         options |= kOOTextureMinFilterMipMap;
     867             :                 }
     868             :         }
     869             :         
     870             :         if (!gOOTextureInfo.textureMaxLevelAvailable)
     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             :                  */
     877             :                 if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap)
     878             :                 {
     879             :                         options ^= kOOTextureMinFilterMipMap ^ kOOTextureMinFilterLinear;
     880             :                 }
     881             :         }
     882             :         
     883             :         if (options & kOOTextureAllowRectTexture)
     884             :         {
     885             :                 // Apply rectangle texture restrictions (regardless of whether rectangle textures are available, for consistency)
     886             :                 options &= kOOTextureFlagsAllowedForRectangleTexture;
     887             :                 if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap)
     888             :                 {
     889             :                         options = (kOOTextureMinFilterMask & ~kOOTextureMinFilterMask) | kOOTextureMinFilterLinear;
     890             :                 }
     891             :                 
     892             : #if GL_EXT_texture_rectangle
     893             :                 if (!gOOTextureInfo.rectangleTextureAvailable)
     894             :                 {
     895             :                         options &= ~kOOTextureAllowRectTexture;
     896             :                 }
     897             : #else
     898             :                 options &= ~kOOTextureAllowRectTexture;
     899             : #endif
     900             :         }
     901             :         
     902             :         options &= kOOTextureDefinedFlags;
     903             :         
     904             :         return options;
     905             : }
     906             : 
     907             : 
     908           0 : NSString *OOGenerateTextureCacheKey(NSString *directory, NSString *name, OOTextureFlags options, float anisotropy, float lodBias)
     909             : {
     910             :         if (!gOOTextureInfo.anisotropyAvailable || (options & kOOTextureMinFilterMask) != kOOTextureMinFilterMipMap)
     911             :         {
     912             :                 anisotropy = 0.0f;
     913             :         }
     914             :         if (!gOOTextureInfo.textureLODBiasAvailable || (options & kOOTextureMinFilterMask) != kOOTextureMinFilterMipMap)
     915             :         {
     916             :                 lodBias = 0.0f;
     917             :         }
     918             :         options = OOApplyTextureOptionDefaults(options & ~kOOTextureNoFNFMessage);
     919             :         
     920             :         return [NSString stringWithFormat:@"%@%@%@:0x%.4X/%g/%g", directory ? directory : (NSString *)@"", directory ? @"/" : @"", name, options, anisotropy, lodBias];
     921             : }
     922             : 
     923             : 
     924           0 : NSString *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             : }

Generated by: LCOV version 1.14