cocos2d-x中CCTextureCache图片资源的异步加载

cocos2d-x中CCTextureCache图片资源的异步加载

如果没有预先加载图片,则可以通过addImageAsync()函数实现异步加载,该函数通过创建一个加载线程来加载图片,并且在主线程中通过调用回调函数来读取该图片资源纹理。其主要过程如下:

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);
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值