parent
a88373a4fc
commit
9cc343b5eb
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue