2010-07-16 14:15:06 +08:00
|
|
|
/****************************************************************************
|
|
|
|
Copyright (c) 2010 cocos2d-x.org
|
|
|
|
|
|
|
|
http://www.cocos2d-x.org
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
|
|
all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "CCTextureCache.h"
|
2010-07-16 16:28:11 +08:00
|
|
|
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
#include "CCTextureCache.h"
|
|
|
|
#include "CCTexture2D.h"
|
|
|
|
#include "ccMacros.h"
|
2010-07-20 14:29:18 +08:00
|
|
|
//#include "CCDirector.h"
|
2010-07-16 16:28:11 +08:00
|
|
|
//#include "Support/CCFileUtils.h"
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
/// @todo EAGLContext static EAGLContext *auxEAGLcontext = NULL;
|
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
class CCAsyncObject : NSObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
fpAsyncCallback m_pfnCallback;
|
|
|
|
NSObject* m_pTarget;
|
2010-07-20 13:49:13 +08:00
|
|
|
std::string * m_pData;
|
2010-07-16 16:28:11 +08:00
|
|
|
public:
|
|
|
|
CCAsyncObject();
|
|
|
|
~CCAsyncObject()
|
|
|
|
{
|
|
|
|
CCLOGINFO("cocos2d: deallocing CCAsyncObject.");
|
|
|
|
CCX_SAFE_DELETE(m_pTarget);
|
|
|
|
CCX_SAFE_DELETE(m_pData);
|
|
|
|
}
|
|
|
|
};
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
// implementation CCTextureCache
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
// TextureCache - Alloc, Init & Dealloc
|
|
|
|
static CCTextureCache *g_sharedTextureCache;
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
CCTextureCache * CCTextureCache::sharedTextureCache()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
if (!g_sharedTextureCache)
|
|
|
|
g_sharedTextureCache = new CCTextureCache();
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
return g_sharedTextureCache;
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
CCTextureCache::CCTextureCache()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
NSAssert(sharedTextureCache == NULL, "Attempted to allocate a second instance of a singleton.");
|
|
|
|
/** @todo NSMutableDictionary , NSLock
|
|
|
|
textures = [[NSMutableDictionary dictionaryWithCapacity: 10] retain];
|
|
|
|
dictLock = [[NSLock alloc] init];
|
|
|
|
contextLock = [[NSLock alloc] init];*/
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
CCTextureCache::~CCTextureCache()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
CCLOG("cocos2d: deallocing CCTextureCache.");
|
|
|
|
/// @todo release
|
|
|
|
// [textures release];
|
|
|
|
// [dictLock release];
|
|
|
|
// [contextLock release];
|
|
|
|
// [auxEAGLcontext release];
|
|
|
|
// auxEAGLcontext = nil;
|
|
|
|
// sharedTextureCache = nil;
|
|
|
|
// [super dealloc];
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
void CCTextureCache::purgeSharedTextureCache()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
CCX_SAFE_RELEASE(g_sharedTextureCache);
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
std::string CCTextureCache::description()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo CCMutableDictionary
|
|
|
|
return [NSString stringWithFormat:@"<%@ = %08X | num of textures = %i>", [self class], self, [textures count]];
|
|
|
|
char des[100];
|
|
|
|
sprintf_s(des, 100, "<CCTextureCache | num of textures = %d>", m_pTextures->count());
|
|
|
|
string ret(des);
|
|
|
|
|
|
|
|
return ret;*/
|
|
|
|
return NULL;
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
// TextureCache - Add Images
|
|
|
|
void CCTextureCache::addImageWithAsyncObject(CCAsyncObject* async)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-16 14:15:06 +08:00
|
|
|
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
|
|
|
|
|
|
|
|
// textures will be created on the main OpenGL context
|
|
|
|
// it seems that in SDK 2.2.x there can't be 2 threads creating textures at the same time
|
|
|
|
// the lock is used for this purpose: issue #472
|
|
|
|
[contextLock lock];
|
|
|
|
if( auxEAGLcontext == nil ) {
|
|
|
|
auxEAGLcontext = [[EAGLContext alloc]
|
|
|
|
initWithAPI:kEAGLRenderingAPIOpenGLES1
|
|
|
|
sharegroup:[[[[CCDirector sharedDirector] openGLView] context] sharegroup]];
|
|
|
|
|
|
|
|
if( ! auxEAGLcontext )
|
|
|
|
CCLOG(@"cocos2d: TextureCache: Could not create EAGL context");
|
|
|
|
}
|
|
|
|
|
|
|
|
if( [EAGLContext setCurrentContext:auxEAGLcontext] ) {
|
|
|
|
|
|
|
|
// load / create the texture
|
|
|
|
CCTexture2D *tex = [self addImage:async.data];
|
|
|
|
|
|
|
|
// The callback will be executed on the main thread
|
|
|
|
[async.target performSelectorOnMainThread:async.selector withObject:tex waitUntilDone:NO];
|
|
|
|
|
|
|
|
[EAGLContext setCurrentContext:nil];
|
|
|
|
} else {
|
|
|
|
CCLOG(@"cocos2d: TetureCache: EAGLContext error");
|
|
|
|
}
|
|
|
|
[contextLock unlock];
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
[autoreleasepool release];*/
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-20 13:49:13 +08:00
|
|
|
-(void) addImageAsync: (string & ) filename target:(id)target selector:(SEL)selector
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
|
|
|
NSAssert(filename != nil, @"TextureCache: fileimage MUST not be nill");
|
|
|
|
|
|
|
|
// optimization
|
|
|
|
|
|
|
|
CCTexture2D * tex;
|
|
|
|
|
|
|
|
if( (tex=[textures objectForKey: filename] ) ) {
|
|
|
|
[target performSelector:selector withObject:tex];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// schedule the load
|
|
|
|
|
|
|
|
CCAsyncObject *asyncObject = [[CCAsyncObject alloc] init];
|
|
|
|
asyncObject.selector = selector;
|
|
|
|
asyncObject.target = target;
|
|
|
|
asyncObject.data = filename;
|
|
|
|
|
|
|
|
[NSThread detachNewThreadSelector:@selector(addImageWithAsyncObject:) toTarget:self withObject:asyncObject];
|
|
|
|
[asyncObject release];
|
2010-07-16 16:28:11 +08:00
|
|
|
}*/
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
CCTexture2D * CCTextureCache::addImage(string & path)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-20 13:49:13 +08:00
|
|
|
NSAssert(!path.empty(), "TextureCache: fileimage MUST not be nill");
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
CCTexture2D * tex = NULL;
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
// MUTEX:
|
|
|
|
// Needed since addImageAsync calls this method from a different thread
|
2010-07-16 16:28:11 +08:00
|
|
|
/** todo
|
2010-07-16 14:15:06 +08:00
|
|
|
[dictLock lock];
|
|
|
|
|
|
|
|
tex=[textures objectForKey: path];
|
|
|
|
|
|
|
|
if( ! tex ) {
|
|
|
|
|
|
|
|
// Split up directory and filename
|
2010-07-20 13:49:13 +08:00
|
|
|
string & fullpath = [CCFileUtils fullPathFromRelativePath: path ];
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
// all images are handled by UIImage except PVR extension that is handled by our own handler
|
|
|
|
if ( [[path lowercaseString] hasSuffix:@".pvr"] )
|
|
|
|
tex = [self addPVRTCImage:fullpath];
|
|
|
|
else {
|
|
|
|
|
|
|
|
// prevents overloading the autorelease pool
|
|
|
|
UIImage *image = [ [UIImage alloc] initWithContentsOfFile: fullpath ];
|
|
|
|
tex = [ [CCTexture2D alloc] initWithImage: image ];
|
|
|
|
[image release];
|
|
|
|
|
|
|
|
|
|
|
|
if( tex )
|
|
|
|
[textures setObject: tex forKey:path];
|
|
|
|
else
|
|
|
|
CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);
|
|
|
|
|
|
|
|
|
|
|
|
[tex release];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
[dictLock unlock];
|
2010-07-16 16:28:11 +08:00
|
|
|
*/
|
2010-07-16 14:15:06 +08:00
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
CCTexture2D* CCTextureCache::addPVRTCImage(string & path, int bpp, bool hasAlpha, int width)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
NSAssert(!path.empty(), "TextureCache: fileimage MUST not be nill");
|
2010-07-16 16:28:11 +08:00
|
|
|
NSAssert( bpp==2 || bpp==4, "TextureCache: bpp must be either 2 or 4");
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
CCTexture2D * tex;
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-16 14:15:06 +08:00
|
|
|
if( (tex=[textures objectForKey: path] ) ) {
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Split up directory and filename
|
2010-07-20 13:49:13 +08:00
|
|
|
string & fullpath = [CCFileUtils fullPathFromRelativePath:path];
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
NSData *nsdata = [[NSData alloc] initWithContentsOfFile:fullpath];
|
|
|
|
tex = [[CCTexture2D alloc] initWithPVRTCData:[nsdata bytes] level:0 bpp:bpp hasAlpha:alpha length:w];
|
|
|
|
if( tex )
|
|
|
|
[textures setObject: tex forKey:path];
|
|
|
|
else
|
|
|
|
CCLOG(@"cocos2d: Couldn't add PVRTCImage:%@ in CCTextureCache",path);
|
|
|
|
|
|
|
|
[nsdata release];
|
2010-07-16 16:28:11 +08:00
|
|
|
*/
|
|
|
|
tex->autorelease();
|
|
|
|
return tex;
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
CCTexture2D * CCTextureCache::addPVRTCImage(string & fileimage)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-20 13:49:13 +08:00
|
|
|
NSAssert(!fileimage.empty(), "TextureCache: fileimage MUST not be nill");
|
2010-07-16 14:15:06 +08:00
|
|
|
|
|
|
|
CCTexture2D * tex;
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-16 14:15:06 +08:00
|
|
|
if( (tex=[textures objectForKey: fileimage] ) ) {
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
tex = [[CCTexture2D alloc] initWithPVRTCFile: fileimage];
|
|
|
|
if( tex )
|
|
|
|
[textures setObject: tex forKey:fileimage];
|
|
|
|
else
|
|
|
|
CCLOG(@"cocos2d: Couldn't add PVRTCImage:%@ in CCTextureCache",fileimage);
|
2010-07-16 16:28:11 +08:00
|
|
|
*/
|
|
|
|
tex->autorelease();
|
|
|
|
return tex;
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-20 13:49:13 +08:00
|
|
|
-(CCTexture2D*) addCGImage: (CGImageRef) imageref forKey: (string & )key
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
|
|
|
NSAssert(imageref != nil, @"TextureCache: image MUST not be nill");
|
|
|
|
|
|
|
|
CCTexture2D * tex = nil;
|
|
|
|
|
|
|
|
// If key is nil, then create a new texture each time
|
|
|
|
if( key && (tex=[textures objectForKey: key] ) ) {
|
|
|
|
return tex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// prevents overloading the autorelease pool
|
|
|
|
UIImage *image = [[UIImage alloc] initWithCGImage:imageref];
|
|
|
|
tex = [[CCTexture2D alloc] initWithImage: image];
|
|
|
|
[image release];
|
|
|
|
|
|
|
|
if(tex && key)
|
|
|
|
[textures setObject: tex forKey:key];
|
|
|
|
else
|
|
|
|
CCLOG(@"cocos2d: Couldn't add CGImage in CCTextureCache");
|
|
|
|
|
|
|
|
return [tex autorelease];
|
2010-07-16 16:28:11 +08:00
|
|
|
}*/
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
// TextureCache - Remove
|
2010-07-16 14:15:06 +08:00
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
void CCTextureCache::removeAllTextures()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
/// @todo [textures removeAllObjects];
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
void CCTextureCache::removeUnusedTextures()
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-16 14:15:06 +08:00
|
|
|
NSArray *keys = [textures allKeys];
|
|
|
|
for( id key in keys ) {
|
|
|
|
id value = [textures objectForKey:key];
|
|
|
|
if( [value retainCount] == 1 ) {
|
|
|
|
CCLOG(@"cocos2d: CCTextureCache: removing unused texture: %@", key);
|
|
|
|
[textures removeObjectForKey:key];
|
|
|
|
}
|
2010-07-16 16:28:11 +08:00
|
|
|
}*/
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
void CCTextureCache::removeTexture(CCTexture2D* tex)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-16 16:28:11 +08:00
|
|
|
/** @todo
|
2010-07-16 14:15:06 +08:00
|
|
|
if( ! tex )
|
|
|
|
return;
|
|
|
|
|
|
|
|
NSArray *keys = [textures allKeysForObject:tex];
|
|
|
|
|
|
|
|
for( NSUInteger i = 0; i < [keys count]; i++ )
|
2010-07-16 16:28:11 +08:00
|
|
|
[textures removeObjectForKey:[keys objectAtIndex:i]];*/
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-20 13:49:13 +08:00
|
|
|
void CCTextureCache::removeTextureForKey(string & textureKeyName)
|
2010-07-16 14:15:06 +08:00
|
|
|
{
|
2010-07-20 13:49:13 +08:00
|
|
|
if( textureKeyName.empty() )
|
2010-07-16 14:15:06 +08:00
|
|
|
return;
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
/// @todo [textures removeObjectForKey:textureKeyName];
|
2010-07-16 14:15:06 +08:00
|
|
|
}
|
|
|
|
|
2010-07-16 16:28:11 +08:00
|
|
|
|