summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiaohong Bao <bao@lindenlab.com>2012-06-12 17:01:48 -0600
committerXiaohong Bao <bao@lindenlab.com>2012-06-12 17:01:48 -0600
commit0d80aced2477500ed5912a34e2bc4b6dbf8f719a (patch)
treeeb1688c9f32e7daa2596ee8f51b867ea07041897
parent8e5f12a43fdbdd377bd4362020c05a591dd2ffd8 (diff)
for SH-3073: implement a fast cache system for texture fetching
-rw-r--r--indra/llimage/llimage.cpp9
-rw-r--r--indra/llimage/llimage.h2
-rwxr-xr-xindra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/lltexturecache.cpp188
-rw-r--r--indra/newview/lltexturecache.h17
-rwxr-xr-xindra/newview/lltexturefetch.cpp4
-rw-r--r--indra/newview/llviewertexture.cpp46
-rw-r--r--indra/newview/llviewertexture.h4
-rw-r--r--indra/newview/llviewertexturelist.cpp51
-rw-r--r--indra/newview/llviewertexturelist.h2
10 files changed, 316 insertions, 18 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 6775b005f4..e6b838c5b2 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -292,11 +292,16 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components)
++sRawImageCount;
}
-LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
+LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
: LLImageBase()
{
mMemType = LLMemType::MTYPE_IMAGERAW;
- if(allocateDataSize(width, height, components))
+
+ if(no_copy)
+ {
+ setDataAndSize(data, width, height, components);
+ }
+ else if(allocateDataSize(width, height, components))
{
memcpy(getData(), data, width*height*components);
}
diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h
index 46e6d1a901..99023351c2 100644
--- a/indra/llimage/llimage.h
+++ b/indra/llimage/llimage.h
@@ -189,7 +189,7 @@ protected:
public:
LLImageRaw();
LLImageRaw(U16 width, U16 height, S8 components);
- LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
+ LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
// Construct using createFromFile (used by tools)
//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 5fe51c97c5..1911943842 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -3259,6 +3259,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>FastCacheFetchEnabled</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable texture fast cache fetching if set</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <string>1</string>
+ </map>
<key>FeatureManagerHTTPTable</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp
index 8632890bbb..a61e2d5c86 100644
--- a/indra/newview/lltexturecache.cpp
+++ b/indra/newview/lltexturecache.cpp
@@ -50,6 +50,8 @@
const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE;//1024;
const F32 TEXTURE_CACHE_PURGE_AMOUNT = .20f; // % amount to reduce the cache by when it exceeds its limit
const F32 TEXTURE_CACHE_LRU_SIZE = .10f; // % amount for LRU list (low overhead to regenerate)
+const S32 TEXTURE_FAST_CACHE_ENTRY_OVERHEAD = sizeof(S32) * 4; //w, h, c, level
+const S32 TEXTURE_FAST_CACHE_ENTRY_SIZE = 16 * 16 * 4 + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD;
class LLTextureCacheWorker : public LLWorkerClass
{
@@ -283,9 +285,12 @@ public:
LLTextureCacheRemoteWorker(LLTextureCache* cache, U32 priority, const LLUUID& id,
U8* data, S32 datasize, S32 offset,
S32 imagesize, // for writes
+ LLPointer<LLImageRaw> raw, S32 discardlevel,
LLTextureCache::Responder* responder)
: LLTextureCacheWorker(cache, priority, id, data, datasize, offset, imagesize, responder),
- mState(INIT)
+ mState(INIT),
+ mRawImage(raw),
+ mRawDiscardLevel(discardlevel)
{
}
@@ -303,6 +308,8 @@ private:
};
e_state mState;
+ LLPointer<LLImageRaw> mRawImage;
+ S32 mRawDiscardLevel;
};
@@ -559,6 +566,11 @@ bool LLTextureCacheRemoteWorker::doWrite()
if(idx < 0)
{
idx = mCache->setHeaderCacheEntry(mID, entry, mImageSize, mDataSize); // create the new entry.
+ if(idx >= 0)
+ {
+ //write to the fast cache.
+ llassert_always(mCache->writeToFastCache(idx, mRawImage, mRawDiscardLevel));
+ }
}
else
{
@@ -658,6 +670,7 @@ bool LLTextureCacheRemoteWorker::doWrite()
// Nothing else to do at that point...
done = true;
}
+ mRawImage = NULL;
// Clean up and exit
return done;
@@ -744,10 +757,14 @@ LLTextureCache::LLTextureCache(bool threaded)
mWorkersMutex(NULL),
mHeaderMutex(NULL),
mListMutex(NULL),
+ mFastCacheMutex(NULL),
mHeaderAPRFile(NULL),
mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
mTexturesSizeTotal(0),
- mDoPurge(FALSE)
+ mDoPurge(FALSE),
+ mFastCachep(NULL),
+ mFastCachePoolp(NULL),
+ mFastCachePadBuffer(NULL)
{
}
@@ -755,6 +772,9 @@ LLTextureCache::~LLTextureCache()
{
clearDeleteList() ;
writeUpdatedEntries() ;
+ delete mFastCachep;
+ delete mFastCachePoolp;
+ FREE_MEM(LLImageBase::getPrivatePool(), mFastCachePadBuffer);
}
//////////////////////////////////////////////////////////////////////////////
@@ -879,15 +899,15 @@ BOOL LLTextureCache::isInLocal(const LLUUID& id)
//////////////////////////////////////////////////////////////////////////////
//static
-const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB
-F32 LLTextureCache::sHeaderCacheVersion = 1.4f;
-U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE;
+F32 LLTextureCache::sHeaderCacheVersion = 1.7f;
+U32 LLTextureCache::sCacheMaxEntries = 1024 * 1024; //~1 million textures.
S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit
const char* entries_filename = "texture.entries";
const char* cache_filename = "texture.cache";
const char* old_textures_dirname = "textures";
//change the location of the texture cache to prevent from being deleted by old version viewers.
const char* textures_dirname = "texturecache";
+const char* fast_cache_filename = "FastCache.cache";
void LLTextureCache::setDirNames(ELLPath location)
{
@@ -896,6 +916,7 @@ void LLTextureCache::setDirNames(ELLPath location)
mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, entries_filename);
mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, cache_filename);
mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname);
+ mFastCacheFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, fast_cache_filename);
}
void LLTextureCache::purgeCache(ELLPath location)
@@ -938,8 +959,8 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
{
llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
- S64 header_size = (max_size * 2) / 10;
- S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE;
+ S64 header_size = (max_size / 100) * 36; //0.36 * max_size
+ S64 max_entries = header_size / (TEXTURE_CACHE_ENTRY_SIZE + TEXTURE_FAST_CACHE_ENTRY_SIZE);
sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries));
header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE;
max_size -= header_size;
@@ -981,6 +1002,7 @@ S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL texture_cache
purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it
llassert_always(getPending() == 0) ; //should not start accessing the texture cache before initialized.
+ openFastCache(true);
return max_size; // unused cache space
}
@@ -1751,7 +1773,7 @@ LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 pri
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
NULL, size, offset,
- 0, responder);
+ 0, NULL, 0, responder);
handle_t handle = worker->read();
mReaders[handle] = worker;
return handle;
@@ -1789,6 +1811,7 @@ bool LLTextureCache::readComplete(handle_t handle, bool abort)
LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority,
U8* data, S32 datasize, S32 imagesize,
+ LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder)
{
if (mReadOnly)
@@ -1807,12 +1830,159 @@ LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 prio
LLMutexLock lock(&mWorkersMutex);
LLTextureCacheWorker* worker = new LLTextureCacheRemoteWorker(this, priority, id,
data, datasize, 0,
- imagesize, responder);
+ imagesize, rawimage, discardlevel, responder);
handle_t handle = worker->write();
mWriters[handle] = worker;
return handle;
}
+//called in the main thread
+LLPointer<LLImageRaw> LLTextureCache::readFromFastCache(const LLUUID& id, S32& discardlevel)
+{
+ U32 offset;
+ {
+ LLMutexLock lock(&mHeaderMutex);
+ id_map_t::const_iterator iter = mHeaderIDMap.find(id);
+ if(iter == mHeaderIDMap.end())
+ {
+ return NULL; //not in the cache
+ }
+
+ offset = iter->second;
+ }
+ offset *= TEXTURE_FAST_CACHE_ENTRY_SIZE;
+
+ U8* data;
+ S32 head[4];
+ {
+ LLMutexLock lock(&mFastCacheMutex);
+
+ openFastCache();
+
+ mFastCachep->seek(APR_SET, offset);
+
+ llassert_always(mFastCachep->read(head, TEXTURE_FAST_CACHE_ENTRY_OVERHEAD) == TEXTURE_FAST_CACHE_ENTRY_OVERHEAD);
+
+ S32 image_size = head[0] * head[1] * head[2];
+ if(!image_size) //invalid
+ {
+ closeFastCache();
+ return NULL;
+ }
+ discardlevel = head[3];
+
+ data = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), image_size);
+ llassert_always(mFastCachep->read(data, image_size) == image_size);
+ closeFastCache();
+ }
+ LLPointer<LLImageRaw> raw = new LLImageRaw(data, head[0], head[1], head[2], true);
+
+ return raw;
+}
+
+//return the fast cache location
+bool LLTextureCache::writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel)
+{
+ //rescale image if needed
+ S32 w, h, c;
+ w = raw->getWidth();
+ h = raw->getHeight();
+ c = raw->getComponents();
+ S32 i = 0 ;
+
+ while(((w >> i) * (h >> i) * c) > TEXTURE_FAST_CACHE_ENTRY_SIZE - TEXTURE_FAST_CACHE_ENTRY_OVERHEAD)
+ {
+ ++i ;
+ }
+
+ if(i)
+ {
+ w >>= i;
+ h >>= i;
+ if(w * h *c > 0) //valid
+ {
+ LLPointer<LLImageRaw> newraw = new LLImageRaw(raw->getData(), raw->getWidth(), raw->getHeight(), raw->getComponents());
+ newraw->scale(w, h) ;
+ raw = newraw;
+
+ discardlevel += i ;
+ }
+ }
+
+ //copy data
+ memcpy(mFastCachePadBuffer, &w, sizeof(S32));
+ memcpy(mFastCachePadBuffer + sizeof(S32), &h, sizeof(S32));
+ memcpy(mFastCachePadBuffer + sizeof(S32) * 2, &c, sizeof(S32));
+ memcpy(mFastCachePadBuffer + sizeof(S32) * 3, &discardlevel, sizeof(S32));
+ if(w * h * c > 0) //valid
+ {
+ memcpy(mFastCachePadBuffer + TEXTURE_FAST_CACHE_ENTRY_OVERHEAD, raw->getData(), w * h * c);
+ }
+ S32 offset = id * TEXTURE_FAST_CACHE_ENTRY_SIZE;
+
+ {
+ LLMutexLock lock(&mFastCacheMutex);
+
+ openFastCache();
+
+ mFastCachep->seek(APR_SET, offset);
+ llassert_always(mFastCachep->write(mFastCachePadBuffer, TEXTURE_FAST_CACHE_ENTRY_SIZE) == TEXTURE_FAST_CACHE_ENTRY_SIZE);
+
+ closeFastCache(true);
+ }
+
+ return true;
+}
+
+void LLTextureCache::openFastCache(bool first_time)
+{
+ if(!mFastCachep)
+ {
+ if(first_time)
+ {
+ if(!mFastCachePadBuffer)
+ {
+ mFastCachePadBuffer = (U8*)ALLOCATE_MEM(LLImageBase::getPrivatePool(), TEXTURE_FAST_CACHE_ENTRY_SIZE);
+ }
+ mFastCachePoolp = new LLVolatileAPRPool();
+ if (LLAPRFile::isExist(mFastCacheFileName, mFastCachePoolp))
+ {
+ mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
+ }
+ else
+ {
+ mFastCachep = new LLAPRFile(mFastCacheFileName, APR_CREATE|APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
+ }
+ }
+ else
+ {
+ mFastCachep = new LLAPRFile(mFastCacheFileName, APR_READ|APR_WRITE|APR_BINARY, mFastCachePoolp) ;
+ }
+
+ mFastCacheTimer.reset();
+ }
+ return;
+}
+
+void LLTextureCache::closeFastCache(bool forced)
+{
+ static const F32 timeout = 10.f ; //seconds
+
+ if(!mFastCachep)
+ {
+ return ;
+ }
+
+ if(!forced && mFastCacheTimer.getElapsedTimeF32() < timeout)
+ {
+ return ;
+ }
+
+ delete mFastCachep;
+ mFastCachep = NULL;
+ return;
+}
+
bool LLTextureCache::writeComplete(handle_t handle, bool abort)
{
lockWorkers();
diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h
index dd0cc9b4bd..e3fc957fd2 100644
--- a/indra/newview/lltexturecache.h
+++ b/indra/newview/lltexturecache.h
@@ -36,6 +36,7 @@
class LLImageFormatted;
class LLTextureCacheWorker;
+class LLImageRaw;
class LLTextureCache : public LLWorkerThread
{
@@ -113,8 +114,9 @@ public:
handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size,
ReadResponder* responder);
bool readComplete(handle_t handle, bool abort);
- handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize,
+ handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, LLPointer<LLImageRaw> rawimage, S32 discardlevel,
WriteResponder* responder);
+ LLPointer<LLImageRaw> readFromFastCache(const LLUUID& id, S32& discardlevel);
bool writeComplete(handle_t handle, bool abort = false);
void prioritizeWrite(handle_t handle);
@@ -171,12 +173,18 @@ private:
void lockHeaders() { mHeaderMutex.lock(); }
void unlockHeaders() { mHeaderMutex.unlock(); }
+ void openFastCache(bool first_time = false);
+ void closeFastCache(bool forced = false);
+ bool writeToFastCache(S32 id, LLPointer<LLImageRaw> raw, S32 discardlevel);
+
private:
// Internal
LLMutex mWorkersMutex;
LLMutex mHeaderMutex;
LLMutex mListMutex;
+ LLMutex mFastCacheMutex;
LLAPRFile* mHeaderAPRFile;
+ LLVolatileAPRPool* mFastCachePoolp;
typedef std::map<handle_t, LLTextureCacheWorker*> handle_map_t;
handle_map_t mReaders;
@@ -193,12 +201,17 @@ private:
// HEADERS (Include first mip)
std::string mHeaderEntriesFileName;
std::string mHeaderDataFileName;
+ std::string mFastCacheFileName;
EntriesInfo mHeaderEntriesInfo;
std::set<S32> mFreeList; // deleted entries
std::set<LLUUID> mLRU;
- typedef std::map<LLUUID,S32> id_map_t;
+ typedef std::map<LLUUID, S32> id_map_t;
id_map_t mHeaderIDMap;
+ LLAPRFile* mFastCachep;
+ LLFrameTimer mFastCacheTimer;
+ U8* mFastCachePadBuffer;
+
// BODIES (TEXTURES minus headers)
std::string mTexturesDirName;
typedef std::map<LLUUID,S32> size_map_t;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index f47f3864dd..5a9cf4aeb6 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1536,7 +1536,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID);
mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority,
mFormattedImage->getData(), datasize,
- mFileSize, responder);
+ mFileSize, mRawImage, mDecodedDiscard, responder);
// fall through
}
@@ -3551,7 +3551,7 @@ void LLTextureFetchDebugger::debugCacheWrite()
mFetchingHistory[i].mCacheHandle = mTextureCache->writeToCache(mFetchingHistory[i].mID, LLWorkerThread::PRIORITY_NORMAL,
mFetchingHistory[i].mFormattedImage->getData(), mFetchingHistory[i].mFetchedSize,
mFetchingHistory[i].mDecodedLevel == 0 ? mFetchingHistory[i].mFetchedSize : mFetchingHistory[i].mFetchedSize + 1,
- new LLDebuggerCacheWriteResponder(this, i));
+ NULL, 0, new LLDebuggerCacheWriteResponder(this, i));
}
}
}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index ad7e50b788..1226c98f1c 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -62,6 +62,7 @@
#include "llmediaentry.h"
#include "llvovolume.h"
#include "llviewermedia.h"
+#include "lltexturecache.h"
///////////////////////////////////////////////////////////////////////////////
// statics
@@ -1257,6 +1258,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
mRequestDeltaTime = 0.f;
mForSculpt = FALSE ;
mIsFetched = FALSE ;
+ mInFastCacheList = FALSE;
mCachedRawImage = NULL ;
mCachedRawDiscardLevel = -1 ;
@@ -1313,7 +1315,38 @@ void LLViewerFetchedTexture::cleanup()
mCachedRawDiscardLevel = -1 ;
mCachedRawImageReady = FALSE ;
mSavedRawImage = NULL ;
- mSavedRawDiscardLevel = -1;
+}
+
+//access the fast cache
+void LLViewerFetchedTexture::loadFromFastCache()
+{
+ if(!mInFastCacheList)
+ {
+ return; //no need to access the fast cache.
+ }
+ mInFastCacheList = FALSE;
+
+ mRawImage = LLAppViewer::getTextureCache()->readFromFastCache(getID(), mRawDiscardLevel) ;
+ if(mRawImage.notNull())
+ {
+ mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
+ mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
+ setTexelsPerImage();
+
+ if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
+ {
+ //discard all oversized textures.
+ destroyRawImage();
+ setIsMissingAsset();
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL ;
+ }
+ else
+ {
+ mRequestedDiscardLevel = mDesiredDiscardLevel + 1;
+ mIsRawImageValid = TRUE;
+ addToCreateTexture() ;
+ }
+ }
}
void LLViewerFetchedTexture::setForSculpt()
@@ -1741,7 +1774,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired;
ddiscard = llclamp(ddiscard, 0, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY);
priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR;
- setAdditionalDecodePriority(1.0f) ;//boost the textures without any data so far.
+ setAdditionalDecodePriority(0.1f) ;//boost the textures without any data so far.
}
else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel))
{
@@ -1953,6 +1986,10 @@ bool LLViewerFetchedTexture::updateFetch()
{
return false; // process any raw image data in callbacks before replacing
}
+ if(mInFastCacheList)
+ {
+ return false;
+ }
S32 current_discard = getCurrentDiscardLevelForFetching() ;
S32 desired_discard = getDesiredDiscardLevel();
@@ -2082,6 +2119,11 @@ bool LLViewerFetchedTexture::updateFetch()
{
make_request = false;
}
+ else if(mCachedRawImage.notNull() && (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
+ {
+ make_request = false;
+ switchToCachedImage() ; //use the cached raw data first
+ }
//else if (!isJustBound() && mCachedRawImageReady)
//{
// make_request = false;
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index c1ebbd9ebe..c2747c980e 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -497,6 +497,9 @@ public:
void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;}
void forceToDeleteRequest();
+ void loadFromFastCache();
+ void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; }
+ bool isInFastCacheList() { return mInFastCacheList; }
protected:
/*virtual*/ void switchToCachedImage();
S32 getCurrentDiscardLevelForFetching() ;
@@ -516,6 +519,7 @@ private:
private:
BOOL mFullyLoaded;
BOOL mInDebug;
+ BOOL mInFastCacheList;
protected:
std::string mLocalFileName;
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 42d8cb9272..385c61f6c7 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -276,6 +276,7 @@ void LLViewerTextureList::shutdown()
// Flush all of the references
mLoadingStreamList.clear();
mCreateTextureList.clear();
+ mFastCacheList.clear();
mUUIDMap.clear();
@@ -453,6 +454,8 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
LLGLenum primary_format,
LLHost request_from_host)
{
+ static LLCachedControl<bool> fast_cache_fetching_enabled(gSavedSettings, "FastCacheFetchEnabled");
+
LLPointer<LLViewerFetchedTexture> imagep ;
switch(texture_type)
{
@@ -490,6 +493,11 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
imagep->forceActive() ;
}
+ if(fast_cache_fetching_enabled)
+ {
+ mFastCacheList.insert(imagep);
+ imagep->setInFastCacheList(true);
+ }
return imagep ;
}
@@ -595,6 +603,7 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_MARK_DIRTY("Dirty Images");
static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_PRIORITIES("Prioritize");
static LLFastTimer::DeclareTimer FTM_IMAGE_CALLBACKS("Callbacks");
static LLFastTimer::DeclareTimer FTM_IMAGE_FETCH("Fetch");
+static LLFastTimer::DeclareTimer FTM_FAST_CACHE_IMAGE_FETCH("Fast Cache Fetch");
static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create");
static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats");
@@ -619,6 +628,11 @@ void LLViewerTextureList::updateImages(F32 max_time)
LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory));
LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
+ {
+ //loading from fast cache
+ LLFastTimer t(FTM_FAST_CACHE_IMAGE_FETCH);
+ max_time -= updateImagesLoadingFastCache(max_time);
+ }
{
LLFastTimer t(FTM_IMAGE_UPDATE_PRIORITIES);
@@ -771,6 +785,10 @@ void LLViewerTextureList::updateImagesDecodePriorities()
{
continue;
}
+ if(imagep->isInFastCacheList())
+ {
+ continue; //wait for loading from the fast cache.
+ }
imagep->processTextureStats();
F32 old_priority = imagep->getDecodePriority();
@@ -864,6 +882,36 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
return create_timer.getElapsedTimeF32();
}
+F32 LLViewerTextureList::updateImagesLoadingFastCache(F32 max_time)
+{
+ if (gGLManager.mIsDisabled) return 0.0f;
+ if(mFastCacheList.empty())
+ {
+ return 0.f;
+ }
+
+ //
+ // loading texture raw data from the fast cache directly.
+ //
+
+ LLTimer timer;
+ image_list_t::iterator enditer = mFastCacheList.begin();
+ for (image_list_t::iterator iter = mFastCacheList.begin();
+ iter != mFastCacheList.end();)
+ {
+ image_list_t::iterator curiter = iter++;
+ enditer = iter;
+ LLViewerFetchedTexture *imagep = *curiter;
+ imagep->loadFromFastCache();
+ if (timer.getElapsedTimeF32() > max_time)
+ {
+ break;
+ }
+ }
+ mFastCacheList.erase(mFastCacheList.begin(), enditer);
+ return timer.getElapsedTimeF32();
+}
+
void LLViewerTextureList::forceImmediateUpdate(LLViewerFetchedTexture* imagep)
{
if(!imagep)
@@ -985,6 +1033,9 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
{
LLTimer timer;
+ //loading from fast cache
+ updateImagesLoadingFastCache(max_time);
+
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
for (image_priority_list_t::iterator iter = mImageList.begin();
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index b8f74a4ec6..3dda973d3f 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -121,6 +121,7 @@ private:
F32 updateImagesCreateTextures(F32 max_time);
F32 updateImagesFetchTextures(F32 max_time);
void updateImagesUpdateStats();
+ F32 updateImagesLoadingFastCache(F32 max_time);
void addImage(LLViewerFetchedTexture *image);
void deleteImage(LLViewerFetchedTexture *image);
@@ -174,6 +175,7 @@ public:
image_list_t mLoadingStreamList;
image_list_t mCreateTextureList;
image_list_t mCallbackList;
+ image_list_t mFastCacheList;
// Note: just raw pointers because they are never referenced, just compared against
std::set<LLViewerFetchedTexture*> mDirtyTextureList;