• 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 ”, 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 ”, 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 ”, 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);
            }
        }
    }
  • 相关阅读:
    多工作簿引用
    Record.ToTable记录到表Table.FromRecords/Record.To…(Power Query 之 M 语言)
    Sumif矩阵区域条件求和
    计算不重复
    数值到列表(Power Query 之 M 语言)
    Table.FromList列表到表Table.From…(Power Query 之 M 语言)
    图文表排版
    按比例划分等级
    Diocp HTTPServer 支持SVG
    责任声明和转载声明 .
  • 原文地址:https://www.cnblogs.com/zhepama/p/3302700.html
Copyright © 2020-2023  润新知