46#define RGBA_IMAGE_TYPE GL_UNSIGNED_INT_8_8_8_8_REV
47#elif OOLITE_LITTLE_ENDIAN
48#define RGBA_IMAGE_TYPE GL_UNSIGNED_BYTE
50#error Neither OOLITE_BIG_ENDIAN nor OOLITE_LITTLE_ENDIAN is defined as nonzero!
54@interface OOConcreteTexture (Private)
59#if OO_TEXTURE_CUBE_MAP
65#if OOTEXTURE_RELOADABLE
79 options:(uint32_t)options
80 anisotropy:(GLfloat)anisotropy
81 lodBias:(GLfloat)lodBias
92 _loader = [loader retain];
95#if GL_EXT_texture_filter_anisotropic
98#if GL_EXT_texture_lod_bias
105 _name = [[NSString alloc] initWithFormat:@"<%@>", [loader class]];
117- (id)initWithPath:(NSString *)path
119 options:(uint32_t)options
120 anisotropy:(
float)anisotropy
121 lodBias:(GLfloat)lodBias
130 if ((
self = [
self initWithLoader:loader key:key options:options anisotropy:anisotropy lodBias:lodBias]))
132#if OOTEXTURE_RELOADABLE
133 _path = [path retain];
144 OOLog(_trace ?
@"texture.allocTrace.dealloc" :
@"texture.dealloc",
@"Deallocating and uncaching texture %p",
self);
147#if OOTEXTURE_RELOADABLE
153 if (_textureName != 0)
156 OOGL(glDeleteTextures(1, &_textureName));
163#ifndef OOTEXTURE_NO_CACHE
164 [
self removeFromCaches];
179- (NSString *) descriptionComponents
181 NSString *stateDesc =
nil;
187 stateDesc = [NSString stringWithFormat:@"%u x %u", _width, _height];
191 stateDesc =
@"LOAD ERROR";
196 stateDesc =
@"loading";
199 return [NSString stringWithFormat:@"%@, %@", _key, stateDesc];
203- (NSString *) shortDescriptionComponents
212 if (_name !=
nil)
return _name;
214#if OOTEXTURE_RELOADABLE
215 NSString *name = [_path lastPathComponent];
217 NSString *name = [[[[
self cacheKey] componentsSeparatedByString:@":"] objectAtIndex:0] lastPathComponent];
220 NSString *channelSuffix =
nil;
224 channelSuffix =
@":r";
228 channelSuffix =
@":g";
232 channelSuffix =
@":b";
236 channelSuffix =
@":a";
240 if (channelSuffix !=
nil) name = [name stringByAppendingString:channelSuffix];
251 if (
EXPECT_NOT(!_loaded)) [
self setUpTexture];
252 else if (
EXPECT_NOT(!_uploaded)) [
self uploadTexture];
253 else OOGL(glBindTexture([
self glTextureTarget], _textureName));
255#if GL_EXT_texture_lod_bias
261- (void)ensureFinishedLoading
263 if (!_loaded) [
self setUpTexture];
267- (BOOL) isFinishedLoading
269 return _loaded || [_loader isReady];
273- (NSString *) cacheKey
281 [
self ensureFinishedLoading];
283 return NSMakeSize(_width, _height);
287- (NSSize) originalDimensions
289 [
self ensureFinishedLoading];
291 return NSMakeSize(_originalWidth, _originalHeight);
297 [
self ensureFinishedLoading];
299 return _mipLevels != 0;
303- (struct
OOPixMap) copyPixMapRepresentation
305 [
self ensureFinishedLoading];
312 px =
OOMakePixMap(_bytes, _width, _height, _format, 0, 0);
315#if OOTEXTURE_RELOADABLE
321 GLenum format, internalFormat, type;
322 if (!
DecodeFormat(_format, _options, &format, &internalFormat, &type))
327 if (![
self isCubeMap])
333 glGetTexImage(GL_TEXTURE_2D, 0, format, type, px.
pixels);
335#if OO_TEXTURE_CUBE_MAP
340 uint8_t *pixels = px.
pixels;
343 for (i = 0; i < 6; i++)
345 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, type, pixels);
357- (BOOL) isRectangleTexture
359#if GL_EXT_texture_rectangle
360 return _isRectTexture;
369#if OO_TEXTURE_CUBE_MAP
377- (NSSize)texCoordsScale
379#if GL_EXT_texture_rectangle
384 return NSMakeSize(1.0f, 1.0f);
388 return NSMakeSize(_width, _height);
396 return NSMakeSize(1.0f, 1.0f);
401 [
self ensureFinishedLoading];
402 return [
self texCoordsScale];
406 return NSMakeSize(1.0f, 1.0f);
411- (GLint)glTextureName
413 [
self ensureFinishedLoading];
421@implementation OOConcreteTexture (Private)
428 if ([_loader getResult:&pm format:&_format originalWidth:&_originalWidth originalHeight:&_originalHeight])
434#if OO_TEXTURE_CUBE_MAP
441#if !defined(NDEBUG) && OOTEXTURE_RELOADABLE
444 static unsigned dumpID = 0;
445 NSString *name = [NSString stringWithFormat:@"tex dump %u \"%@\"", ++dumpID,[
self name]];
446 OOLog(
@"texture.trace.dump",
@"Dumped traced texture %@ to \'%@.png\'",
self, name);
451 [
self uploadTexture];
475 GLenum texTarget = [
self glTextureTarget];
477 OOGL(glGenTextures(1, &_textureName));
478 OOGL(glBindTexture(texTarget, _textureName));
485#if OO_TEXTURE_CUBE_MAP
486 if (texTarget == GL_TEXTURE_CUBE_MAP)
488 wrapS = wrapT = clampMode;
489 OOGL(glTexParameteri(texTarget, GL_TEXTURE_WRAP_R, clampMode));
493 OOGL(glTexParameteri(texTarget, GL_TEXTURE_WRAP_S, wrapS));
494 OOGL(glTexParameteri(texTarget, GL_TEXTURE_WRAP_T, wrapT));
502 filter = GL_LINEAR_MIPMAP_LINEAR;
504 else filter = GL_LINEAR;
505 OOGL(glTexParameteri(texTarget, GL_TEXTURE_MIN_FILTER, filter));
507#if GL_EXT_texture_filter_anisotropic
510 OOGL(glTexParameterf(texTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, _anisotropy));
517 else filter = GL_LINEAR;
518 OOGL(glTexParameteri(texTarget, GL_TEXTURE_MAG_FILTER, filter));
522 if (texTarget == GL_TEXTURE_2D)
524 [
self uploadTextureDataWithMipMap:mipMap format:_format];
525 OOLog(
@"texture.upload",
@"Uploaded texture %u (%ux%u pixels, %@)", _textureName, _width, _height, _key);
527#if OO_TEXTURE_CUBE_MAP
528 else if (texTarget == GL_TEXTURE_CUBE_MAP)
530 [
self uploadTextureCubeMapDataWithMipMap:mipMap format:_format];
531 OOLog(
@"texture.upload",
@"Uploaded cube map texture %u (%ux%ux6 pixels, %@)", _textureName, _width, _width, _key);
536 [NSException raise:NSInternalInconsistencyException format:@"Unhandled texture target 0x%X.", texTarget];
542#if OOTEXTURE_RELOADABLE
555 GLenum glFormat = 0, internalFormat = 0, type = 0;
559 char *bytes = _bytes;
564 if (!
DecodeFormat(format, _options, &glFormat, &internalFormat, &type))
return;
566 while (0 < w && 0 < h)
568 OOGL(glTexImage2D(GL_TEXTURE_2D, level++, internalFormat, w, h, 0, glFormat, type, bytes));
570 bytes += w * components * h;
576 _mipLevels = level - 1;
581#if OO_TEXTURE_CUBE_MAP
586 GLenum glFormat = 0, internalFormat = 0, type = 0;
587 if (!
DecodeFormat(format, _options, &glFormat, &internalFormat, &type))
return;
591 size_t sideSize = _width * _width * components;
594 sideSize = sideSize * 4 / 3;
595 sideSize = (sideSize + 15) & ~15;
599 for (side = 0; side < 6; side++)
601 char *bytes = _bytes;
602 bytes += side * sideSize;
604 unsigned w = _width, level = 0;
608 OOGL(glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + side, level++, internalFormat, w, w, 0, glFormat, type, bytes));
610 bytes += w * w * components;
620 GLenum texTarget = GL_TEXTURE_2D;
621#if OO_TEXTURE_CUBE_MAP
624 texTarget = GL_TEXTURE_CUBE_MAP;
633 if (_loaded && _uploaded && _valid)
638 OOGL(glDeleteTextures(1, &_textureName));
641#if OOTEXTURE_RELOADABLE
644 OOLog(
@"texture.reload",
@"Reloading texture %@",
self);
659#if OOTEXTURE_RELOADABLE
673 NSCParameterAssert(outFormat != NULL && outInternalFormat != NULL && outType != NULL);
678 *outFormat = GL_RGBA;
679 *outInternalFormat = options &
kOOTextureSRGBA ? GL_SRGB_ALPHA : GL_RGBA;
680 *outType = RGBA_IMAGE_TYPE;
686 *outFormat = GL_ALPHA;
687 *outInternalFormat = GL_ALPHA8;
691 *outFormat = GL_LUMINANCE;
692 *outInternalFormat = GL_LUMINANCE8;
694 *outType = GL_UNSIGNED_BYTE;
698 *outFormat = GL_LUMINANCE_ALPHA;
699 *outInternalFormat = GL_LUMINANCE8_ALPHA8;
700 *outType = GL_UNSIGNED_BYTE;
static BOOL DecodeFormat(OOTextureDataFormat format, uint32_t options, GLenum *outFormat, GLenum *outInternalFormat, GLenum *outType)
#define OOLog(class, format,...)
NSString *const kOOLogParameterError
#define OO_ENTER_OPENGL()
void OODumpPixMap(OOPixMap pixMap, NSString *name)
unsigned short OOPixMapBytesPerPixelForFormat(OOPixMapFormat format) PURE_FUNC
const OOPixMap kOONullPixMap
OOPixMap OOAllocatePixMap(OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize)
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize)
BOOL OOIsValidPixMap(OOPixMap pixMap)
OOPixMap OODuplicatePixMap(OOPixMap srcPixMap, size_t desiredSize)
#define GL_TEXTURE_MAX_LEVEL
uint8_t OOTextureComponentsForFormat(OOTextureDataFormat format)
@ kOOTextureDataGrayscaleAlpha
@ kOOTextureDataGrayscale
@ kOOTextureAllowRectTexture
@ kOOTextureExtractChannelA
@ kOOTextureExtractChannelB
@ kOOTextureMagFilterMask
@ kOOTextureExtractChannelMask
@ kOOTextureMinFilterMask
@ kOOTextureMinFilterMipMap
@ kOOTextureMagFilterNearest
@ kOOTextureExtractChannelG
@ kOOTextureExtractChannelR
@ kOOTextureMinFilterNearest
OOTextureInfo gOOTextureInfo
id loaderWithPath:options:(NSString *path,[options] uint32_t options)
unsigned anisotropyAvailable
unsigned clampToEdgeAvailable
unsigned cubeMapAvailable
unsigned textureLODBiasAvailable