views:

205

answers:

1

I've got a nice and short method to load textures in my iPhone app, where I glGenTextures(13, &textures[0]);. Of course at the end of it I do glDeleteTextures(13, textures);, but the memory isn't fully released untill I comment out this line: CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);' (which of course results in having the textures totally black) although the next line says:

 CGContextRelease(textureContext);

This is the full code for loading the textures:

- (void)loadTexture:(NSString *)name intoLocation:(GLuint)location {
    CGImageRef textureImage = [UIImage imageNamed:name].CGImage;
    if (textureImage == nil) {
        NSLog(@"Failed to load texture image");
        return;
    }

    NSInteger texWidth = CGImageGetWidth(textureImage);
    NSInteger texHeight = CGImageGetHeight(textureImage);

    GLubyte *textureData = (GLubyte *)malloc(texWidth * texHeight << 2);

    int k, l = texWidth * texHeight << 2;
    for (k=0; k<l; k++) textureData[k] = 0;

    CGContextRef textureContext = CGBitmapContextCreate(textureData, texWidth, texHeight, 8, texWidth << 2, CGImageGetColorSpace(textureImage),
                                                        kCGImageAlphaPremultipliedLast);
    CGContextTranslateCTM(textureContext, 0, texHeight);
    CGContextScaleCTM(textureContext, 1.0, -1.0);
    CGContextDrawImage(textureContext, CGRectMake(0.0, 0.0, (float)texWidth, (float)texHeight), textureImage);
    CGContextRelease(textureContext);

    glBindTexture(GL_TEXTURE_2D, location);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData);

    free(textureData);
    glEnable(GL_TEXTURE_2D);
}
A: 

CGImage decodes its data lazily the first time its drawn. It holds on to the decoded data.

The UIImage class caches UIImage instances by name, and the instances hold the CGImages which are holding the decoded data. The UIImage cache is purged in response to low memory warnings.

If this is causing too much memory use in your app, you want to control the creation and destruction of UIImages more carefully, which means not using +[UIImage imageNamed:].

On the other hand, usually an app doesn't have that many named images - it's a static set determined at compile time. If you were just wondering about this memory usage, there you go.

Ken
Thanks for Your reply. I don't use many textures in my game (1MB), so it's OK for me, but since this memory cannot be released I wonder why this way of loading textures is commonly seen in tutorials.Could anyone recommend a better way of loading textures?
Twig
`+[UIImage imageNamed:]` is very appropriate for Cocoa apps that will keep using the image, less so for images that you're just using once to dump into a texture. I'm not familiar with GL, so I'm not sure what's easiest. You can get a path to the image with `-[NSBundle pathForResource:ofType:]`. If you'd rather have the image data (in the on-disk format), you can use `-[NSData initWithContentsOfFile:]`. If the UIImage is convenient and you just don't like the cache, `-[UIImage initWithContentsOfFile:]`.
Ken