1.创建线程,用于后台加载图片
2.将对于需要加载的图片放入图片资源队列中
3.callback函数设定,用于将加载完成的图片转为纹理,等待使用其调用是由CCTimer::update调用的。
4.addImageAsyncCallBack函数在处理完纹理转换,还会调用addImageAsync传入的SEL_CallFuncO selector,实现用户加载图片纹理之后的具体处理。
void addImageAsync(const char *path, CCObject *target, SEL_CallFuncO selector); 函数实现过程如下: void CCTextureCache::addImageAsync(const char *path, CCObject *target, SEL_CallFuncO selector) { CCAssert(path != NULL, “TextureCache: fileimage MUST not be NULL”); CCTexture2D *texture = NULL; // optimization std::string pathKey = path; pathKey = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(pathKey.c_str()); texture = (CCTexture2D*)m_pTextures->objectForKey(pathKey.c_str()); std::string fullpath = pathKey; if (texture != NULL) { if (target && selector) { (target->*selector)(texture); } return; } // lazy init if (s_pSem == NULL) { #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE s_pSem = sem_open(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE, O_CREAT, 0644, 0); if( s_pSem == SEM_FAILED ) { CCLOG( “CCTextureCache async thread semaphore init error: %s\n”, strerror( errno ) ); s_pSem = NULL; return; } #else int semInitRet = sem_init(&s_sem, 0, 0); if( semInitRet < 0 ) { CCLOG( “CCTextureCache async thread semaphore init error: %s\n”, strerror( errno ) ); return; } s_pSem = &s_sem; #endif //创建一个异步信息队列 s_pAsyncStructQueue = new queue<AsyncStruct*>(); //创建一个图片资源队列 s_pImageQueue = new queue<ImageInfo*>(); pthread_mutex_init(&s_asyncStructQueueMutex, NULL); pthread_mutex_init(&s_ImageInfoMutex, NULL); //创建加载图片资源线程,用于加载图片 pthread_create(&s_loadingThread, NULL, loadImage, NULL); need_quit = false; } if (0 == s_nAsyncRefCount) { //创建调度队列,用来根据已加载图片来进行纹理转换 CCDirector::sharedDirector()->getScheduler()->scheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this, 0, false); } ++s_nAsyncRefCount; if (target) { target->retain(); } // generate async struct AsyncStruct *data = new AsyncStruct(); data->filename = fullpath.c_str(); data->target = target; data->selector = selector; // add async struct into queue pthread_mutex_lock(&s_asyncStructQueueMutex); //将需要加载的图片放入异步信息队列 s_pAsyncStructQueue->push(data); pthread_mutex_unlock(&s_asyncStructQueueMutex); sem_post(s_pSem); }创建图片资源 static void* loadImage(void* data) { // create autorelease pool for iOS CCThread thread; thread.createAutoreleasePool(); AsyncStruct *pAsyncStruct = NULL; while (true) { // wait for rendering thread to ask for loading if s_pAsyncStructQueue is empty int semWaitRet = sem_wait(s_pSem); if( semWaitRet < 0 ) { CCLOG( “CCTextureCache async thread semaphore error: %s\n”, strerror( errno ) ); break; } //从异步信息队列中取出 std::queue<AsyncStruct*> *pQueue = s_pAsyncStructQueue; pthread_mutex_lock(&s_asyncStructQueueMutex);// get async struct from queue if (pQueue->empty()) { pthread_mutex_unlock(&s_asyncStructQueueMutex); if (need_quit) break; else continue; } else { pAsyncStruct = pQueue->front(); pQueue->pop(); pthread_mutex_unlock(&s_asyncStructQueueMutex); } const char *filename = pAsyncStruct->filename.c_str(); // compute image type CCImage::EImageFormat imageType = computeImageFormatType(pAsyncStruct->filename); if (imageType == CCImage::kFmtUnKnown) { CCLOG(“unsupported format %s”,filename); delete pAsyncStruct; continue; } //创建图片资源 CCImage *pImage = new CCImage(); if (! pImage->initWithImageFileThreadSafe(filename, imageType)) { delete pImage; CCLOG(“can not load %s”, filename); continue; } // 创建图片资源信息 ImageInfo *pImageInfo = new ImageInfo(); pImageInfo->asyncStruct = pAsyncStruct; pImageInfo->image = pImage; pImageInfo->imageType = imageType; // 把图片资源加入图片资源队列 pthread_mutex_lock(&s_ImageInfoMutex); s_pImageQueue->push(pImageInfo); pthread_mutex_unlock(&s_ImageInfoMutex); } if( s_pSem != NULL ) { #if CC_ASYNC_TEXTURE_CACHE_USE_NAMED_SEMAPHORE sem_unlink(CC_ASYNC_TEXTURE_CACHE_SEMAPHORE); sem_close(s_pSem); #else sem_destroy(s_pSem); #endif s_pSem = NULL; delete s_pAsyncStructQueue; delete s_pImageQueue; } return 0; }
创建图片纹理 void CCTextureCache::addImageAsyncCallBack(float dt) { // 从图片资源队列中取出 std::queue<ImageInfo*> *imagesQueue = s_pImageQueue; pthread_mutex_lock(&s_ImageInfoMutex); if (imagesQueue->empty()) { pthread_mutex_unlock(&s_ImageInfoMutex); } else { ImageInfo *pImageInfo = imagesQueue->front(); imagesQueue->pop(); pthread_mutex_unlock(&s_ImageInfoMutex); AsyncStruct *pAsyncStruct = pImageInfo->asyncStruct; CCImage *pImage = pImageInfo->image; CCObject *target = pAsyncStruct->target; SEL_CallFuncO selector = pAsyncStruct->selector; const char* filename = pAsyncStruct->filename.c_str(); // 创建2D纹理 CCTexture2D *texture = new CCTexture2D(); #if 0 //TODO: (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) texture->initWithImage(pImage, kCCResolutioniPhone); #else texture->initWithImage(pImage); #endif #if CC_ENABLE_CACHE_TEXTURE_DATA // cache the texture file name VolatileTexture::addImageTexture(texture, filename, pImageInfo->imageType); #endif // 加入缓存 m_pTextures->setObject(texture, filename); texture->autorelease(); if (target && selector) { (target->*selector)(texture); target->release(); } pImage->release(); delete pAsyncStruct; delete pImageInfo; –s_nAsyncRefCount; if (0 == s_nAsyncRefCount) { CCDirector::sharedDirector()->getScheduler()->unscheduleSelector(schedule_selector(CCTextureCache::addImageAsyncCallBack), this); } } }
转载于:https://www.cnblogs.com/hzj730/p/3172706.html