diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index b162afddf0..808d218e8e 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -1006,9 +1006,13 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
void LLPreviewTexture::loadAsset()
{
- mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- mImageOldBoostLevel = mImage->getBoostLevel();
- mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ // mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ // mImageOldBoostLevel = mImage->getBoostLevel();
+ // mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
+ mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE);
+ mImageOldBoostLevel = LLGLTexture::BOOST_NONE;
+ //
mImage->forceToSaveRawImage(0) ;
// texture comment decoder
mImage->setLoadedCallback(LLPreviewTexture::onTextureLoaded, 0, TRUE, FALSE, this, &mCallbackTextureList);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 3cd7ccd3ee..16611734c2 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1696,6 +1696,8 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
mNeedsAux = FALSE;
destroyRawImage();
}
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ gTextureList.recalcImageDecodePriority(this);
return res;
}
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 88777fbc15..1718435225 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -710,6 +710,8 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy
addImageToList(new_image);
mUUIDMap[key] = new_image;
new_image->setTextureListType(tex_type);
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ gTextureList.recalcImageDecodePriority(new_image);
}
@@ -721,6 +723,9 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
{
mCallbackList.erase(image);
}
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ mImagesWithChangedPriorities.erase(image);
+
LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType());
llverify(mUUIDMap.erase(key) == 1);
sNumImages--;
@@ -855,121 +860,252 @@ void LLViewerTextureList::clearFetchingRequests()
}
}
+// FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+// NOTE: previous version retained as single block comment, changes extend to the end of updateOneImageDecodePriority
+// void LLViewerTextureList::updateImagesDecodePriorities()
+// {
+// // Update the decode priority for N images each frame
+// {
+// F32 lazy_flush_timeout = 30.f; // stop decoding
+// F32 max_inactive_time = 20.f; // actually delete
+// S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
+
+// //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon.
+// bool reset_timer = gViewerWindow->getProgressView()->getVisible();
+
+// static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
+// const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
+// S32 update_counter = llmin(max_update_count, mUUIDMap.size());
+// uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
+// while ((update_counter-- > 0) && !mUUIDMap.empty())
+// {
+// if (iter == mUUIDMap.end())
+// {
+// iter = mUUIDMap.begin();
+// }
+// mLastUpdateKey = iter->first;
+// LLPointer imagep = iter->second;
+// ++iter; // safe to increment now
+
+// if(imagep->isInDebug() || imagep->isUnremovable())
+// {
+// update_counter--;
+// continue; //is in debug, ignore.
+// }
+
+// //
+// // Flush formatted images using a lazy flush
+// //
+// S32 num_refs = imagep->getNumRefs();
+// if (num_refs == min_refs)
+// {
+// if(reset_timer)
+// {
+// imagep->getLastReferencedTimer()->reset();
+// }
+// else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
+// {
+// // Remove the unused image from the image list
+// deleteImage(imagep);
+// imagep = NULL; // should destroy the image
+// }
+// continue;
+// }
+// else
+// {
+// if(imagep->hasSavedRawImage())
+// {
+// if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
+// {
+// imagep->destroySavedRawImage() ;
+// }
+// }
+
+// if(imagep->isDeleted())
+// {
+// continue ;
+// }
+// else if(imagep->isDeletionCandidate())
+// {
+// imagep->destroyTexture() ;
+// continue ;
+// }
+// else if(imagep->isInactive())
+// {
+// if(reset_timer)
+// {
+// imagep->getLastReferencedTimer()->reset();
+// }
+// else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
+// {
+// imagep->setDeletionCandidate() ;
+// }
+// continue ;
+// }
+// else
+// {
+// imagep->getLastReferencedTimer()->reset();
+
+// //reset texture state.
+// imagep->setInactive() ;
+// }
+// }
+
+// if (!imagep->isInImageList())
+// {
+// continue;
+// }
+// if(imagep->isInFastCacheList())
+// {
+// continue; //wait for loading from the fast cache.
+// }
+
+// imagep->processTextureStats();
+// F32 old_priority = imagep->getDecodePriority();
+// F32 old_priority_test = llmax(old_priority, 0.0f);
+// F32 decode_priority = imagep->calcDecodePriority();
+// F32 decode_priority_test = llmax(decode_priority, 0.0f);
+// // Ignore < 20% difference
+// if ((decode_priority_test < old_priority_test * .8f) ||
+// (decode_priority_test > old_priority_test * 1.25f))
+// {
+// mImageList.erase(imagep) ;
+// imagep->setDecodePriority(decode_priority);
+// mImageList.insert(imagep);
+// }
+// }
+// }
+// }
+
+void LLViewerTextureList::recalcImageDecodePriority(LLPointer image)
+{
+ mImagesWithChangedPriorities.insert(image);
+}
+
void LLViewerTextureList::updateImagesDecodePriorities()
{
// Update the decode priority for N images each frame
+ static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
+ const size_t max_update_count = llmin((S32)(MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
+ S32 update_counter = llmin(max_update_count, (mImagesWithChangedPriorities.size() + mUUIDMap.size()));
+
+ // First, process images whose decode priorities may have changed recently
+ image_list_t::iterator iter2 = mImagesWithChangedPriorities.begin();
+ while ((update_counter-- > 0) && (iter2 != mImagesWithChangedPriorities.end()))
{
- F32 lazy_flush_timeout = 30.f; // stop decoding
- F32 max_inactive_time = 20.f; // actually delete
- S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
+ LLPointer imagep = *iter2;
+ iter2 = mImagesWithChangedPriorities.erase(iter2);
+ updateOneImageDecodePriority(imagep);
+ }
- //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon.
- bool reset_timer = gViewerWindow->getProgressView()->getVisible();
-
- static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32
- const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds.value()) + 1, MAX_PRIO_UPDATES);
- S32 update_counter = llmin(max_update_count, mUUIDMap.size());
- uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
- while ((update_counter-- > 0) && !mUUIDMap.empty())
+ // Second, process all of the images
+ uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateKey);
+ while ((update_counter-- > 0) && !mUUIDMap.empty())
+ {
+ if (iter == mUUIDMap.end())
{
- if (iter == mUUIDMap.end())
- {
- iter = mUUIDMap.begin();
- }
- mLastUpdateKey = iter->first;
- LLPointer imagep = iter->second;
- ++iter; // safe to increment now
-
- if(imagep->isInDebug() || imagep->isUnremovable())
- {
- update_counter--;
- continue; //is in debug, ignore.
- }
-
- //
- // Flush formatted images using a lazy flush
- //
- S32 num_refs = imagep->getNumRefs();
- if (num_refs == min_refs)
- {
- if(reset_timer)
- {
- imagep->getLastReferencedTimer()->reset();
- }
- else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
- {
- // Remove the unused image from the image list
- deleteImage(imagep);
- imagep = NULL; // should destroy the image
- }
- continue;
- }
- else
- {
- if(imagep->hasSavedRawImage())
- {
- if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
- {
- imagep->destroySavedRawImage() ;
- }
- }
-
- if(imagep->isDeleted())
- {
- continue ;
- }
- else if(imagep->isDeletionCandidate())
- {
- imagep->destroyTexture() ;
- continue ;
- }
- else if(imagep->isInactive())
- {
- if(reset_timer)
- {
- imagep->getLastReferencedTimer()->reset();
- }
- else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
- {
- imagep->setDeletionCandidate() ;
- }
- continue ;
- }
- else
- {
- imagep->getLastReferencedTimer()->reset();
-
- //reset texture state.
- imagep->setInactive() ;
- }
- }
-
- if (!imagep->isInImageList())
- {
- continue;
- }
- if(imagep->isInFastCacheList())
- {
- continue; //wait for loading from the fast cache.
- }
-
- imagep->processTextureStats();
- F32 old_priority = imagep->getDecodePriority();
- F32 old_priority_test = llmax(old_priority, 0.0f);
- F32 decode_priority = imagep->calcDecodePriority();
- F32 decode_priority_test = llmax(decode_priority, 0.0f);
- // Ignore < 20% difference
- if ((decode_priority_test < old_priority_test * .8f) ||
- (decode_priority_test > old_priority_test * 1.25f))
- {
- mImageList.erase(imagep) ;
- imagep->setDecodePriority(decode_priority);
- mImageList.insert(imagep);
- }
+ iter = mUUIDMap.begin();
}
+ mLastUpdateKey = iter->first;
+ LLPointer imagep = iter->second;
+ ++iter; // safe to increment now
+ updateOneImageDecodePriority(imagep);
}
}
+void LLViewerTextureList::updateOneImageDecodePriority(LLPointer imagep)
+{
+ const F32 lazy_flush_timeout = 30.f; // stop decoding
+ const F32 max_inactive_time = 20.f; // actually delete
+ const S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference
+
+ bool reset_timer = gViewerWindow->getProgressView()->getVisible();
+
+ if(imagep->isInDebug() || imagep->isUnremovable())
+ {
+ return; //is in debug, ignore.
+ }
+ //
+ // Flush formatted images using a lazy flush
+ //
+ S32 num_refs = imagep->getNumRefs();
+ if (num_refs == min_refs)
+ {
+ if(reset_timer)
+ {
+ imagep->getLastReferencedTimer()->reset();
+ }
+ else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout)
+ {
+ // Remove the unused image from the image list
+ deleteImage(imagep);
+ imagep = NULL; // should destroy the image
+ }
+ return;
+ }
+ else
+ {
+ if(imagep->hasSavedRawImage())
+ {
+ if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time)
+ {
+ imagep->destroySavedRawImage() ;
+ }
+ }
+
+ if(imagep->isDeleted())
+ {
+ return;
+ }
+ else if(imagep->isDeletionCandidate())
+ {
+ imagep->destroyTexture() ;
+ return;
+ }
+ else if(imagep->isInactive())
+ {
+ if(reset_timer)
+ {
+ imagep->getLastReferencedTimer()->reset();
+ }
+ else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time)
+ {
+ imagep->setDeletionCandidate() ;
+ }
+ return;
+ }
+ else
+ {
+ imagep->getLastReferencedTimer()->reset();
+ //reset texture state.
+ imagep->setInactive() ;
+ }
+ }
+ if (!imagep->isInImageList())
+ {
+ return;
+ }
+ if(imagep->isInFastCacheList())
+ {
+ return; //wait for loading from the fast cache.
+ }
+
+ imagep->processTextureStats();
+ F32 old_priority = imagep->getDecodePriority();
+ F32 old_priority_test = llmax(old_priority, 0.0f);
+ F32 decode_priority = imagep->calcDecodePriority();
+ F32 decode_priority_test = llmax(decode_priority, 0.0f);
+ // Ignore < 20% difference
+ if ((decode_priority_test < old_priority_test * .8f) ||
+ (decode_priority_test > old_priority_test * 1.25f))
+ {
+ mImageList.erase(imagep) ;
+ imagep->setDecodePriority(decode_priority);
+ mImageList.insert(imagep);
+ }
+}
+// FIRE-30559
+
void LLViewerTextureList::setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level)
{
if(!tex->setDebugFetching(debug_level))
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 6feae4d897..ca26883763 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -34,6 +34,7 @@
#include "llui.h"
#include
#include
+#include
#include "lluiimage.h"
const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
@@ -147,6 +148,8 @@ public:
private:
void updateImagesDecodePriorities();
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ void updateOneImageDecodePriority(LLPointer imagep);
F32 updateImagesCreateTextures(F32 max_time);
F32 updateImagesFetchTextures(F32 max_time);
void updateImagesUpdateStats();
@@ -219,7 +222,12 @@ public:
// Fast cache stats
static U32 sNumFastCacheReads;
-
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ // Recalculate the image's Decode Priority.
+ // (We'll get to the image eventually even if this method isn't called, but this way it goes
+ // to the head(-ish) of the line.)
+ void recalcImageDecodePriority(LLPointer image);
+ //
private:
typedef std::map< LLTextureKey, LLPointer > uuid_map_t;
uuid_map_t mUUIDMap;
@@ -228,7 +236,11 @@ private:
typedef std::set, LLViewerFetchedTexture::Compare> image_priority_list_t;
image_priority_list_t mImageList;
-
+ // FIRE-30559 texture fetch speedup for user previews (based on patches from Oren Hurvitz)
+ // Images that should be handled first in updateImagesDecodePriorities()
+ image_list_t mImagesWithChangedPriorities;
+ //
+
// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
std::set > mImagePreloads;