summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2024-11-29 15:52:11 +0200
committerAndrey Kleshchev <117672381+akleshchev@users.noreply.github.com>2024-12-03 23:33:28 +0200
commit9cc343b5ebaab50b273205f36b6604e64191caee (patch)
tree5dbcc2de060d2bface92a0739596f2acef47895c /indra/newview
parenta88373a4fc720785f7508bd999abe62a43f617b7 (diff)
#3093 #3055 World Map tiles are blurry #2
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/lltexturefetch.cpp45
-rw-r--r--indra/newview/lltexturefetch.h18
-rw-r--r--indra/newview/llviewertexture.cpp294
-rw-r--r--indra/newview/llviewertexture.h2
4 files changed, 231 insertions, 128 deletions
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 5172fad29d..703030b978 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -2481,7 +2481,7 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L
LL_PROFILE_ZONE_SCOPED;
if (mDebugPause)
{
- return -1;
+ return CREATE_REQUEST_ERROR_DEFAULT;
}
if (f_type == FTT_SERVER_BAKE)
@@ -2497,7 +2497,7 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L
<< host << " != " << worker->mHost << LL_ENDL;
removeRequest(worker, true);
worker = NULL;
- return -1;
+ return CREATE_REQUEST_ERROR_MHOSTS;
}
}
@@ -2550,13 +2550,13 @@ S32 LLTextureFetch::createRequest(FTType f_type, const std::string& url, const L
{
if (worker->wasAborted())
{
- return -1; // need to wait for previous aborted request to complete
+ return CREATE_REQUEST_ERROR_ABORTED; // need to wait for previous aborted request to complete
}
worker->lockWorkMutex(); // +Mw
if (worker->mState == LLTextureFetchWorker::DONE && worker->mDesiredSize == llmax(desired_size, TEXTURE_CACHE_ENTRY_SIZE) && worker->mDesiredDiscard == desired_discard) {
worker->unlockWorkMutex(); // -Mw
- return -1; // similar request has failed or is in a transitional state
+ return CREATE_REQUEST_ERROR_TRANSITION; // similar request has finished, failed or is in a transitional state
}
worker->mActiveCount++;
worker->mNeedsAux = needs_aux;
@@ -3149,6 +3149,43 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
return state;
}
+// Threads: T*
+S32 LLTextureFetch::getLastFetchState(const LLUUID& id, S32& requested_discard, S32& decoded_discard, bool& decoded)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ S32 state = LLTextureFetchWorker::INVALID;
+
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker) // Don't check haveWork, intent is to get whatever is in the worker
+ {
+ worker->lockWorkMutex(); // +Mw
+ state = worker->mState;
+ requested_discard = worker->mDesiredDiscard;
+ decoded_discard = worker->mDecodedDiscard;
+ decoded = worker->mDecoded;
+ worker->unlockWorkMutex(); // -Mw
+ }
+ return state;
+}
+
+// Threads: T*
+S32 LLTextureFetch::getLastRawImage(const LLUUID& id,
+ LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ S32 decoded_discard = -1;
+ LLTextureFetchWorker* worker = getWorker(id);
+ if (worker && !worker->haveWork() && worker->mDecodedDiscard >= 0)
+ {
+ worker->lockWorkMutex(); // +Mw
+ raw = worker->mRawImage;
+ aux = worker->mAuxImage;
+ decoded_discard = worker->mDecodedDiscard;
+ worker->unlockWorkMutex(); // -Mw
+ }
+ return decoded_discard;
+}
+
void LLTextureFetch::dump()
{
LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL;
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index c2c5ec5acc..8ab90896dc 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -76,6 +76,14 @@ public:
// Threads: Tmain
void shutDownImageDecodeThread();
+ enum e_crete_request_errors
+ {
+ CREATE_REQUEST_ERROR_DEFAULT = -1,
+ CREATE_REQUEST_ERROR_MHOSTS = -2,
+ CREATE_REQUEST_ERROR_ABORTED = -3,
+ CREATE_REQUEST_ERROR_TRANSITION = -4,
+ };
+
// Threads: T* (but Tmain mostly)
S32 createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority,
S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http);
@@ -114,12 +122,20 @@ public:
// get the current fetch state, if any, from the given UUID
S32 getFetchState(const LLUUID& id);
- // @return Fetch state of given image and associates statistics
+ // @return Fetch state of an active given image and associates statistics
// See also getStateString
// Threads: T*
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p, bool& can_use_http);
+ // @return Fetch last state of given image
+ // Threads: T*
+ S32 getLastFetchState(const LLUUID& id, S32& requested_discard, S32 &decoded_discard, bool &decoded);
+
+ // @return Fetch last raw image
+ // Threads: T*
+ S32 getLastRawImage(const LLUUID& id, LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux);
+
// Debug utility - generally not safe
void dump();
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 00e1ea4cd3..36cc9bf88f 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1808,6 +1808,141 @@ void LLViewerFetchedTexture::setBoostLevel(S32 level)
}
}
+bool LLViewerFetchedTexture::processFetchResults(S32& desired_discard, S32 current_discard, S32 fetch_discard, F32 decode_priority)
+{
+ // We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
+ if (mRawImage.notNull())
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image");
+ LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
+ if (tester)
+ {
+ mIsFetched = true;
+ tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID));
+ }
+ mRawDiscardLevel = fetch_discard;
+ if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
+ (current_discard < 0 || mRawDiscardLevel < current_discard))
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good");
+
+ // This is going to conflict with Develop, just pick from develop
+ // where it uses setDimensions instead of setTexelsPerImage
+ mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
+ mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
+ setTexelsPerImage();
+
+ if (mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
+ {
+ //discard all oversized textures.
+ destroyRawImage();
+ LL_WARNS() << "oversize, setting as missing" << LL_ENDL;
+ setIsMissingAsset();
+ mRawDiscardLevel = INVALID_DISCARD_LEVEL;
+ mIsFetching = false;
+ mLastPacketTimer.reset();
+ }
+ else
+ {
+ mIsRawImageValid = true;
+ addToCreateTexture();
+ }
+
+ if (mBoostLevel == LLGLTexture::BOOST_ICON)
+ {
+ S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
+ S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
+ if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
+ {
+ // scale oversized icon, no need to give more work to gl
+ // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
+ //
+ // BOOST_ICON gets scaling because profile icons can have a bunch of different formats, not just j2c
+ // Might need another pass to use discard for j2c and scaling for everything else.
+ mRawImage = mRawImage->scaled(expected_width, expected_height);
+ }
+ }
+
+ if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
+ {
+ S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
+ S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
+ if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
+ {
+ // scale oversized icon, no need to give more work to gl
+ // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
+ //
+ // Todo: probably needs to be remade to use discard, all thumbnails are supposed to be j2c,
+ // so no need to scale, should be posible to use discard to scale image down.
+ mRawImage = mRawImage->scaled(expected_width, expected_height);
+ }
+ }
+
+ return true;
+ }
+ else
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed");
+ // Data is ready but we don't need it
+ // (received it already while fetcher was writing to disk)
+ destroyRawImage();
+ return false; // done
+ }
+ }
+
+ if (!mIsFetching)
+ {
+ if ((decode_priority > 0)
+ && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)
+ && mFetchState > 1) // 1 - initial, make sure fetcher did at least something
+ {
+ // We finished but received no data
+ if (getDiscardLevel() < 0)
+ {
+ if (getFTType() != FTT_MAP_TILE)
+ {
+ LL_WARNS() << mID
+ << " Fetch failure, setting as missing, decode_priority " << decode_priority
+ << " mRawDiscardLevel " << mRawDiscardLevel
+ << " current_discard " << current_discard
+ << " stats " << mLastHttpGetStatus.toHex()
+ << " worker state " << mFetchState
+ << LL_ENDL;
+ }
+ setIsMissingAsset();
+ desired_discard = -1;
+ }
+ else
+ {
+ //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
+ if (current_discard >= 0)
+ {
+ mMinDiscardLevel = current_discard;
+ //desired_discard = current_discard;
+ }
+ else
+ {
+ S32 dis_level = getDiscardLevel();
+ mMinDiscardLevel = dis_level;
+ //desired_discard = dis_level;
+ }
+ }
+ destroyRawImage();
+ }
+ else if (mRawImage.notNull())
+ {
+ // We have data, but our fetch failed to return raw data
+ // *TODO: FIgure out why this is happening and fix it
+ // Potentially can happen when TEX_LIST_SCALE and TEX_LIST_STANDARD
+ // get requested for the same texture id at the same time
+ // (two textures, one fetcher)
+ destroyRawImage();
+ }
+ }
+
+ return true;
+}
+
bool LLViewerFetchedTexture::updateFetch()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@@ -1892,127 +2027,12 @@ bool LLViewerFetchedTexture::updateFetch()
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
}
- // We may have data ready regardless of whether or not we are finished (e.g. waiting on write)
- if (mRawImage.notNull())
+ if (!processFetchResults(desired_discard, current_discard, fetch_discard, decode_priority))
{
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - has raw image");
- LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
- if (tester)
- {
- mIsFetched = true;
- tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID));
- }
- mRawDiscardLevel = fetch_discard;
- if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) &&
- (current_discard < 0 || mRawDiscardLevel < current_discard))
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data good");
- mFullWidth = mRawImage->getWidth() << mRawDiscardLevel;
- mFullHeight = mRawImage->getHeight() << mRawDiscardLevel;
- setTexelsPerImage();
-
- if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE)
- {
- //discard all oversized textures.
- destroyRawImage();
- LL_WARNS() << "oversize, setting as missing" << LL_ENDL;
- setIsMissingAsset();
- mRawDiscardLevel = INVALID_DISCARD_LEVEL;
- mIsFetching = false;
- mLastPacketTimer.reset();
- }
- else
- {
- mIsRawImageValid = true;
- addToCreateTexture();
- }
-
- if (mBoostLevel == LLGLTexture::BOOST_ICON)
- {
- S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
- S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
- if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
- {
- // scale oversized icon, no need to give more work to gl
- // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
- mRawImage = mRawImage->scaled(expected_width, expected_height);
- }
- }
-
- if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
- {
- S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
- S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
- if (mRawImage && (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height))
- {
- // scale oversized icon, no need to give more work to gl
- // since we got mRawImage from thread worker and image may be in use (ex: writing cache), make a copy
- mRawImage = mRawImage->scaled(expected_width, expected_height);
- }
- }
-
- return true;
- }
- else
- {
- LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - data not needed");
- // Data is ready but we don't need it
- // (received it already while fetcher was writing to disk)
- destroyRawImage();
- return false; // done
- }
+ return false;
}
- if (!mIsFetching)
- {
- if ((decode_priority > 0)
- && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)
- && mFetchState > 1) // 1 - initial, make sure fetcher did at least something
- {
- // We finished but received no data
- if (getDiscardLevel() < 0)
- {
- if (getFTType() != FTT_MAP_TILE)
- {
- LL_WARNS() << mID
- << " Fetch failure, setting as missing, decode_priority " << decode_priority
- << " mRawDiscardLevel " << mRawDiscardLevel
- << " current_discard " << current_discard
- << " stats " << mLastHttpGetStatus.toHex()
- << " worker state " << mFetchState
- << LL_ENDL;
- }
- setIsMissingAsset();
- desired_discard = -1;
- }
- else
- {
- //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL;
- if(current_discard >= 0)
- {
- mMinDiscardLevel = current_discard;
- //desired_discard = current_discard;
- }
- else
- {
- S32 dis_level = getDiscardLevel();
- mMinDiscardLevel = dis_level;
- //desired_discard = dis_level;
- }
- }
- destroyRawImage();
- }
- else if (mRawImage.notNull())
- {
- // We have data, but our fetch failed to return raw data
- // *TODO: FIgure out why this is happening and fix it
- // Potentially can happen when TEX_LIST_SCALE and TEX_LIST_STANDARD
- // get requested for the same texture id at the same time
- // (two textures, one fetcher)
- destroyRawImage();
- }
- }
- else
+ if (mIsFetching)
{
static const F32 MAX_HOLD_TIME = 5.0f; //seconds to wait before canceling fecthing if decode_priority is 0.f.
if(decode_priority > 0.0f || mStopFetchingTimer.getElapsedTimeF32() > MAX_HOLD_TIME)
@@ -2087,21 +2107,49 @@ bool LLViewerFetchedTexture::updateFetch()
}
// bypass texturefetch directly by pulling from LLTextureCache
- S32 fetch_request_discard = -1;
- fetch_request_discard = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
+ S32 fetch_request_response = -1;
+ S32 worker_discard = -1;
+ fetch_request_response = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority,
w, h, c, desired_discard, needsAux(), mCanUseHTTP);
- if (fetch_request_discard >= 0)
+ if (fetch_request_response >= 0) // positive values and 0 are discard values
{
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - request created");
mHasFetcher = true;
mIsFetching = true;
// in some cases createRequest can modify discard, as an example
// bake textures are always at discard 0
- mRequestedDiscardLevel = llmin(desired_discard, fetch_request_discard);
+ mRequestedDiscardLevel = llmin(desired_discard, fetch_request_response);
mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority,
mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP);
}
+ else if (fetch_request_response == LLTextureFetch::CREATE_REQUEST_ERROR_TRANSITION)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - processing transition error");
+ // Request wasn't created because similar one finished or is in a transitional state, check worker state
+ // As an example can happen if an image (like a server bake always fetches at dis 0), was scaled down to
+ // needed discard after fetching then sudenly needed higher dis and worker wasn't yet deleted. Worker
+ // discard will be identical to requested one and worker will have nothing new to do despite GL image
+ // not being up to data.
+ S32 desired_discard;
+ S32 decoded_discard;
+ bool decoded;
+ S32 fetch_state = LLAppViewer::getTextureFetch()->getLastFetchState(mID, desired_discard, decoded_discard, decoded);
+ if (fetch_state > 1 && decoded && decoded_discard >=0 && decoded_discard <= desired_discard)
+ {
+ // worker actually has the image
+ if (mRawImage.notNull()) sRawCount--;
+ if (mAuxRawImage.notNull()) sAuxCount--;
+ decoded_discard = LLAppViewer::getTextureFetch()->getLastRawImage(getID(), mRawImage, mAuxRawImage);
+ if (mRawImage.notNull()) sRawCount++;
+ if (mAuxRawImage.notNull())
+ {
+ mHasAux = true;
+ sAuxCount++;
+ }
+ processFetchResults(desired_discard, current_discard, decoded_discard, decode_priority);
+ }
+ }
// If createRequest() failed, that means one of two things:
// 1. We're finishing up a request for this UUID, so we
@@ -2923,7 +2971,7 @@ void LLViewerLODTexture::processTextureStats()
mDesiredDiscardLevel = 0;
}
// Generate the request priority and render priority
- else if (mDontDiscard || !mUseMipMaps || (getFTType() == FTT_MAP_TILE))
+ else if (mDontDiscard || !mUseMipMaps)
{
mDesiredDiscardLevel = 0;
if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 1da8548573..4241ef958f 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -423,6 +423,8 @@ private:
void init(bool firstinit) ;
void cleanup() ;
+ bool processFetchResults(S32& desired_discard, S32 current_discard, S32 fetch_discard, F32 decode_priority);
+
void saveRawImage() ;
private: