diff options
Diffstat (limited to 'indra/newview/lltexturecache.cpp')
-rw-r--r-- | indra/newview/lltexturecache.cpp | 210 |
1 files changed, 180 insertions, 30 deletions
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index b60ef6c5ac..474d81b77f 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -50,15 +50,6 @@ class LLTextureCacheWorker : public LLWorkerClass friend class LLTextureCache; private: - enum e_state - { - INIT = 0, - LOCAL = 1, - CACHE = 2, - HEADER = 3, - BODY = 4 - }; - class ReadResponder : public LLLFSThread::Responder { public: @@ -97,10 +88,9 @@ public: S32 imagesize, // for writes LLTextureCache::Responder* responder) : LLWorkerClass(cache, "LLTextureCacheWorker"), + mID(id), mCache(cache), mPriority(priority), - mID(id), - mState(INIT), mReadData(NULL), mWriteData(data), mDataSize(datasize), @@ -121,8 +111,10 @@ public: delete[] mReadData; } - bool doRead(); - bool doWrite(); + // override this interface + virtual bool doRead() = 0; + virtual bool doWrite() = 0; + virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } @@ -133,24 +125,23 @@ public: mBytesRead = bytes; setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority); } - + private: virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) -private: +protected: LLTextureCache* mCache; U32 mPriority; - LLUUID mID; - e_state mState; + LLUUID mID; U8* mReadData; U8* mWriteData; S32 mDataSize; S32 mOffset; S32 mImageSize; - S32 mImageFormat; + EImageCodec mImageFormat; BOOL mImageLocal; LLPointer<LLTextureCache::Responder> mResponder; LLLFSThread::handle_t mFileHandle; @@ -158,19 +149,169 @@ private: LLAtomicS32 mBytesRead; }; +class LLTextureCacheLocalFileWorker : public LLTextureCacheWorker +{ +public: + LLTextureCacheLocalFileWorker(LLTextureCache* cache, U32 priority, const LLString& filename, const LLUUID& id, + U8* data, S32 datasize, S32 offset, + S32 imagesize, // for writes + LLTextureCache::Responder* responder) + : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), + mFileName(filename) + + { + } + + virtual bool doRead(); + virtual bool doWrite(); + +private: + LLString mFileName; +}; + +bool LLTextureCacheLocalFileWorker::doRead() +{ + S32 local_size = ll_apr_file_size(mFileName, mCache->getFileAPRPool()); + + if (local_size > 0 && mFileName.size() > 4) + { + mDataSize = local_size; // Only a complete file is valid + + LLString extension = mFileName.substr(mFileName.size() - 3, 3); + + mImageFormat = LLImageBase::getCodecFromExtension(extension); + + if (mImageFormat == IMG_CODEC_INVALID) + { + llwarns << "Unrecognized file extension " << extension << " for local texture " << mFileName << llendl; + mDataSize = 0; // no data + return true; + } + } + else + { + // file doesn't exist + mDataSize = 0; // no data + return true; + } + +#if USE_LFS_READ + if (mFileHandle == LLLFSThread::nullHandle()) + { + mImageLocal = TRUE; + mImageSize = local_size; + if (!mDataSize || mDataSize + mOffset > local_size) + { + mDataSize = local_size - mOffset; + } + if (mDataSize <= 0) + { + // no more data to read + mDataSize = 0; + return true; + } + mReadData = new U8[mDataSize]; + mBytesRead = -1; + mBytesToRead = mDataSize; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, + new ReadResponder(mCache, mRequestHandle)); + return false; + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "Error reading file from local cache: " << local_filename + << " Bytes: " << mDataSize << " Offset: " << mOffset + << " / " << mDataSize << llendl; + mDataSize = 0; // failed + delete[] mReadData; + mReadData = NULL; + } + return true; + } + else + { + return false; + } + } +#else + if (!mDataSize || mDataSize > local_size) + { + mDataSize = local_size; + } + mReadData = new U8[mDataSize]; + S32 bytes_read = ll_apr_file_read_ex(mFileName, mCache->getFileAPRPool(), + mReadData, mOffset, mDataSize); + if (bytes_read != mDataSize) + { + llwarns << "Error reading file from local cache: " << mFileName + << " Bytes: " << mDataSize << " Offset: " << mOffset + << " / " << mDataSize << llendl; + mDataSize = 0; + delete[] mReadData; + mReadData = NULL; + } + else + { + mImageSize = local_size; + mImageLocal = TRUE; + } + return true; +#endif +} + +bool LLTextureCacheLocalFileWorker::doWrite() +{ + // no writes for local files + return false; +} + +class LLTextureCacheRemoteWorker : public LLTextureCacheWorker +{ +public: + LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, + U8* data, S32 datasize, S32 offset, + S32 imagesize, // for writes + LLTextureCache::Responder* responder) + : LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder), + mState(INIT) + { + } + + virtual bool doRead(); + virtual bool doWrite(); + +private: + enum e_state + { + INIT = 0, + LOCAL = 1, + CACHE = 2, + HEADER = 3, + BODY = 4 + }; + + e_state mState; +}; + + //virtual void LLTextureCacheWorker::startWork(S32 param) { } -bool LLTextureCacheWorker::doRead() +bool LLTextureCacheRemoteWorker::doRead() { S32 local_size = 0; std::string local_filename; if (mState == INIT) { - std::string filename = mCache->getLocalFileName(mID); + std::string filename = mCache->getLocalFileName(mID); local_filename = filename + ".j2c"; local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); if (local_size == 0) @@ -468,19 +609,13 @@ bool LLTextureCacheWorker::doRead() return false; } -bool LLTextureCacheWorker::doWrite() +bool LLTextureCacheRemoteWorker::doWrite() { S32 idx = -1; - if (mState == INIT) - { - llassert_always(mOffset == 0); // Currently don't support offsets - mState = CACHE; - } - // No LOCAL state for write() - if (mState == CACHE) + if (mState == INIT) { S32 cur_imagesize = 0; S32 offset = mOffset; @@ -1250,13 +1385,27 @@ S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* image // Calls from texture pipeline thread (i.e. LLTextureFetch) +LLTextureCache::handle_t LLTextureCache::readFromCache(const LLString& filename, const LLUUID& id, U32 priority, + S32 offset, S32 size, ReadResponder* responder) +{ + // Note: checking to see if an entry exists can cause a stall, + // so let the thread handle it + LLMutexLock lock(&mWorkersMutex); + LLTextureCacheWorker* worker = new LLTextureCacheLocalFileWorker(this, priority, filename, id, + NULL, size, offset, 0, + responder); + handle_t handle = worker->read(); + mReaders[handle] = worker; + return handle; +} + LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size, ReadResponder* responder) { // Note: checking to see if an entry exists can cause a stall, // so let the thread handle it LLMutexLock lock(&mWorkersMutex); - LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, + LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, NULL, size, offset, 0, responder); handle_t handle = worker->read(); @@ -1264,6 +1413,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri return handle; } + bool LLTextureCache::readComplete(handle_t handle, bool abort) { lockWorkers(); @@ -1306,7 +1456,7 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio { LLMutexLock lock(&mWorkersMutex); llassert_always(imagesize > 0); - LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, + LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id, data, datasize, 0, imagesize, responder); handle_t handle = worker->write(); |