diff --git a/src/Core/Materials/OOCombinedEmissionMapGenerator.h b/src/Core/Materials/OOCombinedEmissionMapGenerator.h index eca56e74..e65fe167 100644 --- a/src/Core/Materials/OOCombinedEmissionMapGenerator.h +++ b/src/Core/Materials/OOCombinedEmissionMapGenerator.h @@ -47,6 +47,10 @@ SOFTWARE. OOColor *_illuminationColor; BOOL _isCombinedMap; + uint32_t _textureOptions; + GLfloat _anisotropy; + GLfloat _lodBias; + #ifndef NDEBUG NSString *_emissionDesc; NSString *_illuminationDesc; @@ -60,12 +64,14 @@ SOFTWARE. diffuseMap:(OOTexture *)diffuseMap diffuseColor:(OOColor *)diffuseColor illuminationMap:(OOTextureLoader *)illuminationMapLoader - illuminationColor:(OOColor *)illuminationColor; + illuminationColor:(OOColor *)illuminationColor + optionsSpecifier:(NSDictionary *)spec; - (id) initWithEmissionAndIlluminationMap:(OOTextureLoader *)emissionAndIlluminationMapLoader diffuseMap:(OOTexture *)diffuseMap diffuseColor:(OOColor *)diffuseColor emissionColor:(OOColor *)emissionColor - illuminationColor:(OOColor *)illuminationColor; + illuminationColor:(OOColor *)illuminationColor + optionsSpecifier:(NSDictionary *)spec; @end diff --git a/src/Core/Materials/OOCombinedEmissionMapGenerator.m b/src/Core/Materials/OOCombinedEmissionMapGenerator.m index 4e557395..9eaba5bc 100644 --- a/src/Core/Materials/OOCombinedEmissionMapGenerator.m +++ b/src/Core/Materials/OOCombinedEmissionMapGenerator.m @@ -48,7 +48,8 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); diffuseColor:(OOColor *)diffuseColor illuminationMap:(OOTextureLoader *)illuminationMapLoader illuminationColor:(OOColor *)illuminationColor - isCombinedMap:(BOOL)isCombinedMap; + isCombinedMap:(BOOL)isCombinedMap + optionsSpecifier:(NSDictionary *)spec; @end @@ -61,6 +62,7 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); diffuseColor:(OOColor *)diffuseColor illuminationMap:(OOTextureLoader *)illuminationMapLoader illuminationColor:(OOColor *)illuminationColor + optionsSpecifier:(NSDictionary *)spec { return [self initWithEmissionMap:emissionMapLoader emissionColor:emissionColor @@ -68,7 +70,8 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); diffuseColor:diffuseColor illuminationMap:illuminationMapLoader illuminationColor:illuminationColor - isCombinedMap:NO]; + isCombinedMap:NO + optionsSpecifier:spec]; } @@ -77,6 +80,7 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); diffuseColor:(OOColor *)diffuseColor emissionColor:(OOColor *)emissionColor illuminationColor:(OOColor *)illuminationColor + optionsSpecifier:(NSDictionary *)spec { return [self initWithEmissionMap:emissionAndIlluminationMapLoader emissionColor:emissionColor @@ -84,7 +88,8 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); diffuseColor:diffuseColor illuminationMap:nil illuminationColor:illuminationColor - isCombinedMap:YES]; + isCombinedMap:YES + optionsSpecifier:spec]; } @@ -95,6 +100,7 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); illuminationMap:(OOTextureLoader *)illuminationMapLoader illuminationColor:(OOColor *)illuminationColor isCombinedMap:(BOOL)isCombinedMap + optionsSpecifier:(NSDictionary *)spec { if (emissionMapLoader == nil && illuminationMapLoader == nil) { @@ -104,7 +110,13 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); NSParameterAssert(illuminationMapLoader == nil || !isCombinedMap); - if ((self = [super init])) + uint32_t options; + GLfloat anisotropy; + GLfloat lodBias; + OOInterpretTextureSpecifier(spec, NULL, &options, &anisotropy, &lodBias); + options = OOApplyTetureOptionDefaults(options & ~kOOTextureExtractChannelMask); + + if ((self = [super initWithPath:@"" options:options])) { /* Illumination contribution is: illuminationMap * illuminationColor * diffuseMap * diffuseColor @@ -119,7 +131,7 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); _cacheKey = [[NSString stringWithFormat:@"Combined emission map\nSingle source: %@\nemission:%@ * %@, illumination: %@ * %@ * %@", - _isCombinedMap ? @"yes" : @"no", + isCombinedMap ? @"yes" : @"no", [emissionMapLoader cacheKey], [emissionColor rgbaDescription], [illuminationMapLoader cacheKey], @@ -130,6 +142,10 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); _illuminationColor = [illuminationColor retain]; _isCombinedMap = isCombinedMap; + _textureOptions = options; + _anisotropy = anisotropy; + _lodBias = lodBias; + /* Extract pixmap from diffuse map. This must be done in the main thread even if scheduling is fixed, because it might involve reading back pixels from OpenGL. @@ -234,6 +250,24 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB); #endif +- (uint32_t) textureOptions +{ + return _textureOptions; +} + + +- (GLfloat) anisotropy +{ + return _anisotropy; +} + + +- (GLfloat) lodBias +{ + return _lodBias; +} + + - (NSString *) cacheKey { return _cacheKey; diff --git a/src/Core/Materials/OOMultiTextureMaterial.m b/src/Core/Materials/OOMultiTextureMaterial.m index dc1e0a2b..bf8b3147 100644 --- a/src/Core/Materials/OOMultiTextureMaterial.m +++ b/src/Core/Materials/OOMultiTextureMaterial.m @@ -94,7 +94,8 @@ SOFTWARE. diffuseMap:_diffuseMap diffuseColor:diffuseColor emissionColor:emissionColor - illuminationColor:illuminationColor]; + illuminationColor:illuminationColor + optionsSpecifier:emissionAndIlluminationSpec]; } else { @@ -109,7 +110,8 @@ SOFTWARE. diffuseMap:_diffuseMap diffuseColor:diffuseColor illuminationMap:illuminationMap - illuminationColor:illuminationColor]; + illuminationColor:illuminationColor + optionsSpecifier:emissionSpec ?: illuminationSpec]; } _emissionMap = [[OOTexture textureWithGenerator:[generator autorelease]] retain]; diff --git a/src/Core/Materials/OOPixMapTextureLoader.h b/src/Core/Materials/OOPixMapTextureLoader.h index 2724df37..0480ee71 100644 --- a/src/Core/Materials/OOPixMapTextureLoader.h +++ b/src/Core/Materials/OOPixMapTextureLoader.h @@ -2,7 +2,7 @@ OOPixMapTextureLoader.h -Load a texture from a pixmap. +Load a texture from a pixmap. The loader takes ownership of the pixmap. Copyright (C) 2010-2011 Jens Ayton diff --git a/src/Core/Materials/OOPixMapTextureLoader.m b/src/Core/Materials/OOPixMapTextureLoader.m index de052507..5533844e 100644 --- a/src/Core/Materials/OOPixMapTextureLoader.m +++ b/src/Core/Materials/OOPixMapTextureLoader.m @@ -26,6 +26,7 @@ SOFTWARE. */ #import "OOPixMapTextureLoader.h" +#import "OOTextureScaling.h" @implementation OOPixMapTextureLoader @@ -37,7 +38,7 @@ SOFTWARE. if (freeWhenDone) _pixMap = pixMap; else _pixMap = OODuplicatePixMap(_pixMap, 0); - _texOptions = options; + _texOptions = OOApplyTetureOptionDefaults(options); if (!OOIsValidPixMap(_pixMap)) DESTROY(self); } @@ -56,6 +57,22 @@ SOFTWARE. - (void) loadTexture { + // Generate mip maps if needed. + if ((_texOptions & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap) + { + size_t size = OOMinimumPixMapBufferSize(_pixMap) * 4 / 3; + BOOL generateMipMaps = OOExpandPixMap(&_pixMap, size); + if (generateMipMaps) + { + OOGenerateMipMaps(_pixMap.pixels,_pixMap.width, _pixMap.height, _pixMap.format); + } + else + { + _texOptions = (_texOptions & ~kOOTextureMinFilterMask) | kOOTextureMinFilterMipMap; + } + } + + // Set up output ivars as per OOTextureLoader contract. _data = _pixMap.pixels; _width = _pixMap.width; _height = _pixMap.height; diff --git a/src/Core/Materials/OOTexture.h b/src/Core/Materials/OOTexture.h index 656e04a7..3e75f4a4 100644 --- a/src/Core/Materials/OOTexture.h +++ b/src/Core/Materials/OOTexture.h @@ -284,3 +284,5 @@ BOOL OOCubeMapsAvailable(void); may be NULL. */ BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, uint32_t *outOptions, float *outAnisotropy, float *outLODBias); + +uint32_t OOApplyTetureOptionDefaults(uint32_t options); diff --git a/src/Core/Materials/OOTexture.m b/src/Core/Materials/OOTexture.m index 81f5e34e..9a72a45a 100644 --- a/src/Core/Materials/OOTexture.m +++ b/src/Core/Materials/OOTexture.m @@ -123,53 +123,6 @@ static NSString *sGlobalTraceContext = nil; if (EXPECT_NOT(name == nil)) return nil; if (EXPECT_NOT(!sCheckedExtensions)) [self checkExtensions]; - // Set default flags if needed - if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterDefault) - { - if ([UNIVERSE reducedDetail]) - { - options |= kOOTextureMinFilterLinear; - } - else - { - options |= kOOTextureMinFilterMipMap; - } - } - - if (!gOOTextureInfo.textureMaxLevelAvailable) - { - /* In the unlikely case of an OpenGL system without GL_SGIS_texture_lod, - disable mip-mapping completely. Strictly this is only needed for - non-square textures, but extra logic for such a rare case isn't - worth it. - */ - if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap) - { - options ^= kOOTextureMinFilterMipMap ^ kOOTextureMinFilterLinear; - } - } - - if (options & kOOTextureAllowRectTexture) - { - // Apply rectangle texture restrictions (regardless of whether rectangle textures are available, for consistency) - options &= kOOTextureFlagsAllowedForRectangleTexture; - if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap) - { - options = (kOOTextureMinFilterMask & ~kOOTextureMinFilterMask) | kOOTextureMinFilterLinear; - } - -#if GL_EXT_texture_rectangle - if (!gOOTextureInfo.rectangleTextureAvailable) - { - options &= ~kOOTextureAllowRectTexture; - } -#else - options &= ~kOOTextureAllowRectTexture; -#endif - } - - options &= kOOTextureDefinedFlags; - if (!gOOTextureInfo.anisotropyAvailable || (options & kOOTextureMinFilterMask) != kOOTextureMinFilterMipMap) { anisotropy = 0.0f; @@ -180,7 +133,7 @@ static NSString *sGlobalTraceContext = nil; } noFNF = (options & kOOTextureNoFNFMessage) != 0; - options &= ~kOOTextureNoFNFMessage; + options = OOApplyTetureOptionDefaults(options & ~kOOTextureNoFNFMessage); // Look for existing texture key = [NSString stringWithFormat:@"%@%@%@:0x%.4X/%g/%g", directory ? directory : (NSString *)@"", directory ? @"/" : @"", name, options, anisotropy, lodBias]; @@ -257,7 +210,7 @@ static NSString *sGlobalTraceContext = nil; OOTexture *result = [[[OOConcreteTexture alloc] initWithLoader:generator key:[generator cacheKey] - options:[generator textureOptions] + options:OOApplyTetureOptionDefaults([generator textureOptions]) anisotropy:[generator anisotropy] lodBias:[generator lodBias]] autorelease]; @@ -761,3 +714,56 @@ BOOL OOInterpretTextureSpecifier(id specifier, NSString **outName, uint32_t *out return YES; } + + +uint32_t OOApplyTetureOptionDefaults(uint32_t options) +{ + // Set default flags if needed + if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterDefault) + { + if ([UNIVERSE reducedDetail]) + { + options |= kOOTextureMinFilterLinear; + } + else + { + options |= kOOTextureMinFilterMipMap; + } + } + + if (!gOOTextureInfo.textureMaxLevelAvailable) + { + /* In the unlikely case of an OpenGL system without GL_SGIS_texture_lod, + disable mip-mapping completely. Strictly this is only needed for + non-square textures, but extra logic for such a rare case isn't + worth it. + */ + if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap) + { + options ^= kOOTextureMinFilterMipMap ^ kOOTextureMinFilterLinear; + } + } + + if (options & kOOTextureAllowRectTexture) + { + // Apply rectangle texture restrictions (regardless of whether rectangle textures are available, for consistency) + options &= kOOTextureFlagsAllowedForRectangleTexture; + if ((options & kOOTextureMinFilterMask) == kOOTextureMinFilterMipMap) + { + options = (kOOTextureMinFilterMask & ~kOOTextureMinFilterMask) | kOOTextureMinFilterLinear; + } + +#if GL_EXT_texture_rectangle + if (!gOOTextureInfo.rectangleTextureAvailable) + { + options &= ~kOOTextureAllowRectTexture; + } +#else + options &= ~kOOTextureAllowRectTexture; +#endif + } + + options &= kOOTextureDefinedFlags; + + return options; +} diff --git a/src/Core/OOTextureScaling.m b/src/Core/OOTextureScaling.m index affacecc..7270ba47 100644 --- a/src/Core/OOTextureScaling.m +++ b/src/Core/OOTextureScaling.m @@ -227,7 +227,7 @@ int32_t OSAtomicAdd32(int32_t __theAmount, volatile int32_t *__theValue); BOOL dumpThis = (dumpPlanes & DUMP_CHANNELS) != 0; \ SInt32 dumpID = dumpThis ? OSAtomicAdd32(1, &sPreviousDumpID) : 0; #define DUMP_MIP_MAP_DUMP(px, w, h) if (dumpThis) DumpMipMap(px, w, h, dumpPlanes, dumpID, dumpLevel++); -static void DumpMipMap(void *data, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount planes, SInt32 ID, uint32_t level); +static void DumpMipMap(void *data, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, SInt32 ID, uint32_t level); #else #define DUMP_MIP_MAP_PREPARE(pl) do { (void)pl; } while (0) #define DUMP_MIP_MAP_DUMP(px, w, h) do { (void)px; (void)w; (void)h; } while (0) @@ -878,10 +878,10 @@ static void ScaleToHalf_4_x2(void *srcBytes, void *dstBytes, OOPixMapDimension s #if DUMP_MIP_MAPS -static void DumpMipMap(void *data, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount components, SInt32 ID, uint32_t level) +static void DumpMipMap(void *data, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, SInt32 ID, uint32_t level) { - OOPixMap pixMap = OOMakePixMap(data, width, height, components, 0, 0); - OODumpPixMap(pixMap, [NSString stringWithFormat:@"mipmap dump ID %u lv%u %uch %ux%u", ID, level, components, width, height]); + OOPixMap pixMap = OOMakePixMap(data, width, height, format, 0, 0); + OODumpPixMap(pixMap, [NSString stringWithFormat:@"mipmap dump ID %u lv%u %@ %ux%u", ID, level, OOPixMapFormatName(format), width, height]); } #endif