diff options
Diffstat (limited to 'indra/newview/llviewertexture.cpp')
-rw-r--r-- | indra/newview/llviewertexture.cpp | 1035 |
1 files changed, 677 insertions, 358 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index b80dc7d902..0ad54f238e 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2,31 +2,25 @@ * @file llviewertexture.cpp * @brief Object which handles a received image (and associated texture(s)) * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -82,7 +76,7 @@ LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ; S32 LLViewerTexture::sImageCount = 0; S32 LLViewerTexture::sRawCount = 0; S32 LLViewerTexture::sAuxCount = 0; -LLTimer LLViewerTexture::sEvaluationTimer; +LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0; @@ -102,7 +96,7 @@ F32 LLViewerTexture::sCurrentTime = 0.0f ; BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by -const F32 desired_discard_bias_max = 1.5f; // max number of levels to reduce image quality by +const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by const F64 log_2 = log(2.0); //---------------------------------------------------------------------------------------------- @@ -112,13 +106,53 @@ const F64 log_2 = log(2.0); LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb, S32 discard_level, BOOL need_imageraw, // Needs image raw for the callback - void* userdata ) + void* userdata, + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, + LLViewerFetchedTexture* target, + BOOL pause) : mCallback(cb), mLastUsedDiscard(MAX_DISCARD_LEVEL+1), mDesiredDiscard(discard_level), mNeedsImageRaw(need_imageraw), - mUserData(userdata) + mUserData(userdata), + mSourceCallbackList(src_callback_list), + mPaused(pause) +{ + if(mSourceCallbackList) + { + mSourceCallbackList->insert(target->getID()); + } +} + +LLLoadedCallbackEntry::~LLLoadedCallbackEntry() +{ +} + +void LLLoadedCallbackEntry::removeTexture(LLViewerFetchedTexture* tex) +{ + if(mSourceCallbackList) + { + mSourceCallbackList->erase(tex->getID()) ; + } +} + +//static +void LLLoadedCallbackEntry::cleanUpCallbackList(LLLoadedCallbackEntry::source_callback_list_t* callback_list) { + //clear texture callbacks. + if(callback_list && !callback_list->empty()) + { + for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = callback_list->begin(); + iter != callback_list->end(); ++iter) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter) ; + if(tex) + { + tex->deleteCallbackEntry(callback_list) ; + } + } + callback_list->clear() ; + } } LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image) @@ -293,6 +327,8 @@ void LLViewerTextureManager::init() } } imagep->createGLTexture(0, image_raw); + //cache the raw image + imagep->setCachedRawImage(0, image_raw) ; image_raw = NULL; #else LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); @@ -322,9 +358,7 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sMissingAssetImagep = NULL; LLViewerFetchedTexture::sWhiteImagep = NULL; - LLViewerMediaTexture::cleanup() ; - - LLViewerTexture::cleanupClass() ; + LLViewerMediaTexture::cleanUpClass() ; } //---------------------------------------------------------------------------------------------- @@ -343,11 +377,6 @@ void LLViewerTexture::initClass() } // static -void LLViewerTexture::cleanupClass() -{ -} - -// static S32 LLViewerTexture::getTotalNumOfCategories() { return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; @@ -367,7 +396,7 @@ S32 LLViewerTexture::getCategoryFromIndex(S32 index) } // tuning params -const F32 discard_bias_delta = .05f; +const F32 discard_bias_delta = .25f; const F32 discard_delta_time = 0.5f; const S32 min_non_tex_system_mem = (128<<20); // 128 MB // non-const (used externally @@ -458,6 +487,7 @@ LLViewerTexture::LLViewerTexture(const U32 width, const U32 height, const U8 com mFullHeight = height ; mUseMipMaps = usemipmaps ; mComponents = components ; + setTexelsPerImage(); mID.generate(); sImageCount++; @@ -476,6 +506,7 @@ LLViewerTexture::LLViewerTexture(const LLImageRaw* raw, BOOL usemipmaps) LLViewerTexture::~LLViewerTexture() { + cleanup(); sImageCount--; } @@ -485,6 +516,7 @@ void LLViewerTexture::init(bool firstinit) mFullWidth = 0; mFullHeight = 0; + mTexelsPerImage = 0 ; mUseMipMaps = FALSE ; mComponents = 0 ; @@ -492,11 +524,14 @@ void LLViewerTexture::init(bool firstinit) mDontDiscard = FALSE; mMaxVirtualSize = 0.f; mNeedsGLTexture = FALSE ; - mNeedsResetMaxVirtualSize = FALSE ; + mMaxVirtualSizeResetInterval = 1; + mMaxVirtualSizeResetCounter = mMaxVirtualSizeResetInterval ; mAdditionalDecodePriority = 0.f ; mParcelMedia = NULL ; mNumFaces = 0 ; + mNumVolumes = 0; mFaceList.clear() ; + mVolumeList.clear(); } //virtual @@ -508,7 +543,7 @@ S8 LLViewerTexture::getType() const void LLViewerTexture::cleanup() { mFaceList.clear() ; - + mVolumeList.clear(); if(mGLTexturep) { mGLTexturep->cleanup(); @@ -593,10 +628,10 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co mNeedsGLTexture = TRUE ; } - if(mNeedsResetMaxVirtualSize) + if(!mMaxVirtualSizeResetCounter) { //flag to reset the values because the old values are used. - mNeedsResetMaxVirtualSize = FALSE ; + resetMaxVirtualSizeResetCounter() ; mMaxVirtualSize = virtual_size; mAdditionalDecodePriority = 0.f ; mNeedsGLTexture = needs_gltexture ; @@ -609,9 +644,9 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co void LLViewerTexture::resetTextureStats() { - mMaxVirtualSize = 0.0f; + mMaxVirtualSize = 0.0f ; mAdditionalDecodePriority = 0.f ; - mNeedsResetMaxVirtualSize = FALSE ; + mMaxVirtualSizeResetCounter = 0 ; } //virtual @@ -661,6 +696,42 @@ S32 LLViewerTexture::getNumFaces() const return mNumFaces ; } + +//virtual +void LLViewerTexture::addVolume(LLVOVolume* volumep) +{ + if( mNumVolumes >= mVolumeList.size()) + { + mVolumeList.resize(2 * mNumVolumes + 1) ; + } + mVolumeList[mNumVolumes] = volumep ; + volumep->setIndexInTex(mNumVolumes) ; + mNumVolumes++ ; + mLastVolumeListUpdateTimer.reset() ; +} + +//virtual +void LLViewerTexture::removeVolume(LLVOVolume* volumep) +{ + if(mNumVolumes > 1) + { + S32 index = volumep->getIndexInTex() ; + mVolumeList[index] = mVolumeList[--mNumVolumes] ; + mVolumeList[index]->setIndexInTex(index) ; + } + else + { + mVolumeList.clear() ; + mNumVolumes = 0 ; + } + mLastVolumeListUpdateTimer.reset() ; +} + +S32 LLViewerTexture::getNumVolumes() const +{ + return mNumVolumes ; +} + void LLViewerTexture::reorganizeFaceList() { static const F32 MAX_WAIT_TIME = 20.f; // seconds @@ -680,6 +751,27 @@ void LLViewerTexture::reorganizeFaceList() mFaceList.erase(mFaceList.begin() + mNumFaces, mFaceList.end()); } +void LLViewerTexture::reorganizeVolumeList() +{ + static const F32 MAX_WAIT_TIME = 20.f; // seconds + static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + + if(mNumVolumes + MAX_EXTRA_BUFFER_SIZE > mVolumeList.size()) + { + return ; + } + + if(mLastVolumeListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return ; + } + + mLastVolumeListUpdateTimer.reset() ; + mVolumeList.erase(mVolumeList.begin() + mNumVolumes, mVolumeList.end()); +} + + + //virtual void LLViewerTexture::switchToCachedImage() { @@ -715,8 +807,8 @@ void LLViewerTexture::generateGLTexture() LLImageGL* LLViewerTexture::getGLTexture() const { - llassert_always(mGLTexturep.notNull()) ; - + llassert(mGLTexturep.notNull()) ; + return mGLTexturep ; } @@ -732,7 +824,7 @@ BOOL LLViewerTexture::createGLTexture() BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename, BOOL to_create, S32 category) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; @@ -740,63 +832,70 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image { mFullWidth = mGLTexturep->getCurrentWidth() ; mFullHeight = mGLTexturep->getCurrentHeight() ; - mComponents = mGLTexturep->getComponents() ; + mComponents = mGLTexturep->getComponents() ; + setTexelsPerImage(); } return ret ; } +//virtual +void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) +{ + //nothing here. +} + void LLViewerTexture::setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; mGLTexturep->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes) ; } void LLViewerTexture::setAddressMode(LLTexUnit::eTextureAddressMode mode) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; mGLTexturep->setAddressMode(mode) ; } void LLViewerTexture::setFilteringOption(LLTexUnit::eTextureFilterOptions option) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; mGLTexturep->setFilteringOption(option) ; } //virtual S32 LLViewerTexture::getWidth(S32 discard_level) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getWidth(discard_level) ; } //virtual S32 LLViewerTexture::getHeight(S32 discard_level) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getHeight(discard_level) ; } S32 LLViewerTexture::getMaxDiscardLevel() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getMaxDiscardLevel() ; } S32 LLViewerTexture::getDiscardLevel() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getDiscardLevel() ; } S8 LLViewerTexture::getComponents() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getComponents() ; } LLGLuint LLViewerTexture::getTexName() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getTexName() ; } @@ -821,124 +920,124 @@ BOOL LLViewerTexture::getBoundRecently() const LLTexUnit::eTextureType LLViewerTexture::getTarget(void) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getTarget() ; } BOOL LLViewerTexture::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(imageraw, x_pos, y_pos, width, height) ; } BOOL LLViewerTexture::setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->setSubImage(datap, data_width, data_height, x_pos, y_pos, width, height) ; } void LLViewerTexture::setGLTextureCreated (bool initialized) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; mGLTexturep->setGLTextureCreated (initialized) ; } void LLViewerTexture::setCategory(S32 category) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; mGLTexturep->setCategory(category) ; } LLTexUnit::eTextureAddressMode LLViewerTexture::getAddressMode(void) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getAddressMode() ; } S32 LLViewerTexture::getTextureMemory() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->mTextureMemory ; } LLGLenum LLViewerTexture::getPrimaryFormat() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getPrimaryFormat() ; } BOOL LLViewerTexture::getIsAlphaMask() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getIsAlphaMask() ; } BOOL LLViewerTexture::getMask(const LLVector2 &tc) { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getMask(tc) ; } F32 LLViewerTexture::getTimePassedSinceLastBound() { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getTimePassedSinceLastBound() ; } BOOL LLViewerTexture::getMissed() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getMissed() ; } BOOL LLViewerTexture::isJustBound() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->isJustBound() ; } void LLViewerTexture::forceUpdateBindStats(void) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->forceUpdateBindStats() ; } U32 LLViewerTexture::getTexelsInAtlas() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getTexelsInAtlas() ; } U32 LLViewerTexture::getTexelsInGLTexture() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getTexelsInGLTexture() ; } BOOL LLViewerTexture::isGLTextureCreated() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->isGLTextureCreated() ; } S32 LLViewerTexture::getDiscardLevelInAtlas() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep->getDiscardLevelInAtlas() ; } @@ -952,9 +1051,16 @@ void LLViewerTexture::destroyGLTexture() } } +void LLViewerTexture::setTexelsPerImage() +{ + S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); + S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); + mTexelsPerImage = (F32)fullwidth * fullheight; +} + BOOL LLViewerTexture::isLargeImage() { - return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ; + return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize ; } //virtual @@ -974,12 +1080,6 @@ void LLViewerTexture::updateBindStatsForTester() //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -//static -F32 LLViewerFetchedTexture::maxDecodePriority() -{ - return 6000000.f; -} - LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), mTargetHost(host) @@ -1010,6 +1110,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mRequestedDiscardLevel = -1; mRequestedDownloadPriority = 0.f; mFullyLoaded = FALSE; + mCanUseHTTP = true ; mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; @@ -1029,6 +1130,9 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; + mLoadedCallbackDesiredDiscardLevel = 0; + mPauseLoadedCallBacks = TRUE ; + mNeedsCreateTexture = FALSE; mIsRawImageValid = FALSE; @@ -1041,6 +1145,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mFetchPriority = 0; mDownloadProgress = 0.f; mFetchDeltaTime = 999999.f; + mRequestDeltaTime = 0.f; mForSculpt = FALSE ; mIsFetched = FALSE ; @@ -1082,6 +1187,7 @@ void LLViewerFetchedTexture::cleanup() // We never finished loading the image. Indicate failure. // Note: this allows mLoadedCallbackUserData to be cleaned up. entryp->mCallback( FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData ); + entryp->removeTexture(this) ; delete entryp; } mLoadedCallbackList.clear(); @@ -1193,20 +1299,30 @@ void LLViewerFetchedTexture::destroyTexture() mFullyLoaded = FALSE ; } -// -//do not change the discard level of the loaded texture image. -BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel() +void LLViewerFetchedTexture::addToCreateTexture() { - if (!mLoadedCallbackList.empty()) + bool force_update = false ; + if (getComponents() != mRawImage->getComponents()) { - return TRUE ; - } + // We've changed the number of components, so we need to move any + // objects using this pool to a different pool. + mComponents = mRawImage->getComponents(); + mGLTexturep->setComponents(mComponents) ; + force_update = true ; - return FALSE ; -} + for(U32 i = 0 ; i < mNumFaces ; i++) + { + mFaceList[i]->dirtyTexture() ; + } + + //discard the cached raw image and the saved raw image + mCachedRawImageReady = FALSE ; + mCachedRawDiscardLevel = -1 ; + mCachedRawImage = NULL ; + mSavedRawDiscardLevel = -1 ; + mSavedRawImage = NULL ; + } -void LLViewerFetchedTexture::addToCreateTexture() -{ if(isForSculptOnly()) { //just update some variables, not to create a real GL texture. @@ -1214,6 +1330,11 @@ void LLViewerFetchedTexture::addToCreateTexture() mNeedsCreateTexture = FALSE ; destroyRawImage(); } + else if(!force_update && getDiscardLevel() > -1 && getDiscardLevel() <= mRawDiscardLevel) + { + mNeedsCreateTexture = FALSE ; + destroyRawImage(); + } else { #if 1 @@ -1222,7 +1343,7 @@ void LLViewerFetchedTexture::addToCreateTexture() //so do not scale down the over qualified image. //Note: scaling down image is expensensive. Do it only when very necessary. // - if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !keepReuestedDiscardLevel()) + if(mRequestedDiscardLevel <= mDesiredDiscardLevel && !mForceToSaveRawImage) { S32 w = mFullWidth >> mRawDiscardLevel; S32 h = mFullHeight >> mRawDiscardLevel; @@ -1293,6 +1414,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) mFullWidth = mRawImage->getWidth(); mFullHeight = mRawImage->getHeight(); + setTexelsPerImage(); } else { @@ -1335,24 +1457,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) setActive() ; } - // - // Iterate through the list of image loading callbacks to see - // what sort of data they need. - // - // *TODO: Fix image callback code - BOOL imageraw_callbacks = FALSE; - for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); - iter != mLoadedCallbackList.end(); ) - { - LLLoadedCallbackEntry *entryp = *iter++; - if (entryp->mNeedsImageRaw) - { - imageraw_callbacks = TRUE; - break; - } - } - - if (!imageraw_callbacks) + if (!mForceToSaveRawImage) { mNeedsAux = FALSE; destroyRawImage(); @@ -1364,65 +1469,88 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) //virtual void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { - if(mKnownDrawWidth != width || mKnownDrawHeight != height) + if(mKnownDrawWidth < width || mKnownDrawHeight < height) { - mKnownDrawWidth = width; - mKnownDrawHeight = height; + mKnownDrawWidth = llmax(mKnownDrawWidth, width) ; + mKnownDrawHeight = llmax(mKnownDrawHeight, height) ; mKnownDrawSizeChanged = TRUE ; mFullyLoaded = FALSE ; } - addTextureStats((F32)(width * height)); + addTextureStats((F32)(mKnownDrawWidth * mKnownDrawHeight)); } //virtual void LLViewerFetchedTexture::processTextureStats() { - if(mFullyLoaded)//already loaded - { - return ; - } - - updateVirtualSize() ; - - static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); - - if (textures_fullres) - { - mDesiredDiscardLevel = 0; - } - else if(!mFullWidth || !mFullHeight) - { - mDesiredDiscardLevel = getMaxDiscardLevel() ; + if(mFullyLoaded) + { + if(mDesiredDiscardLevel > mMinDesiredDiscardLevel)//need to load more + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; + mFullyLoaded = FALSE ; + } } else - { - if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) + { + updateVirtualSize() ; + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } + else if(!mFullWidth || !mFullHeight) { - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + mDesiredDiscardLevel = getMaxDiscardLevel() ; + } + else + { + if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight) { - mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048 + } + else + { + mDesiredDiscardLevel = 0; + } } - else + else if(mKnownDrawSizeChanged)//known draw size is set + { + mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, + log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; + mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, mMinDesiredDiscardLevel) ; + } + mKnownDrawSizeChanged = FALSE ; + + if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) { - mDesiredDiscardLevel = 0; + mFullyLoaded = TRUE ; } } - else if(mKnownDrawSizeChanged)//known draw size is set - { - mDesiredDiscardLevel = (S8)llmin(log((F32)mFullWidth / mKnownDrawWidth) / log_2, - log((F32)mFullHeight / mKnownDrawHeight) / log_2) ; - mDesiredDiscardLevel = llclamp(mDesiredDiscardLevel, (S8)0, (S8)getMaxDiscardLevel()) ; - } - mKnownDrawSizeChanged = FALSE ; - - if(getDiscardLevel() >= 0 && (getDiscardLevel() <= mDesiredDiscardLevel)) + } + + if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) //force to refetch the texture. + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; + if(getDiscardLevel() < 0 || getDiscardLevel() > mDesiredDiscardLevel) { - mFullyLoaded = TRUE ; + mFullyLoaded = FALSE ; } } } +const F32 MAX_PRIORITY_PIXEL = 999.f ; //pixel area +const F32 PRIORITY_BOOST_LEVEL_FACTOR = 1000.f ; //boost level +const F32 PRIORITY_DELTA_DISCARD_LEVEL_FACTOR = 100000.f ; //delta discard +const S32 MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY = 4 ; +const F32 PRIORITY_ADDITIONAL_FACTOR = 1000000.f ; //additional +const S32 MAX_ADDITIONAL_LEVEL_FOR_PRIORITY = 8 ; +const F32 PRIORITY_BOOST_HIGH_FACTOR = 10000000.f ;//boost high F32 LLViewerFetchedTexture::calcDecodePriority() { #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -1432,47 +1560,43 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } #endif - if(mFullyLoaded)//already loaded for static texture - { - return -4.0f ; //alreay fetched - } - if (mNeedsCreateTexture) { return mDecodePriority; // no change while waiting to create } - if(mForceToSaveRawImage) + if(mFullyLoaded && !mForceToSaveRawImage)//already loaded for static texture { - return maxDecodePriority() ; + return -1.0f ; //alreay fetched } - - S32 cur_discard = getDiscardLevel(); + + S32 cur_discard = getCurrentDiscardLevelForFetching(); bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); F32 pixel_priority = fsqrtf(mMaxVirtualSize); - F32 priority; + F32 priority = 0.f; + if (mIsMissingAsset) { priority = 0.0f; } else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) { - priority = -1.0f ; + priority = -2.0f ; } else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) { - priority = -1.0f; + priority = -3.0f; } else if (mDesiredDiscardLevel > getMaxDiscardLevel()) { // Don't decode anything we don't need - priority = -1.0f; + priority = -4.0f; } else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data) { priority = 1.f; } - else if (pixel_priority <= 0.f && !have_all_data) + else if (pixel_priority < 0.001f && !have_all_data) { // Not on screen but we might want some data if (mBoostLevel > BOOST_HIGH) @@ -1482,8 +1606,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else { - // Leave the priority as-is - return mDecodePriority; + priority = -5.f; //stop fetching } } else if (cur_discard < 0) @@ -1493,79 +1616,117 @@ F32 LLViewerFetchedTexture::calcDecodePriority() static const F64 log_2 = log(2.0); F32 desired = (F32)(log(32.0/pixel_priority) / log_2); S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; - ddiscard = llclamp(ddiscard, 0, 4); - priority = (ddiscard+1)*100000.f; + 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. } else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) { // larger mips are corrupted - priority = -3.0f; - } - else if (cur_discard <= mDesiredDiscardLevel) - { - priority = -4.0f; + priority = -6.0f; } else { // priority range = 100,000 - 500,000 S32 desired_discard = mDesiredDiscardLevel; - if (getDontDiscard()) - { - desired_discard -= 2; - } - else if (!isJustBound() && mCachedRawImageReady) + if (!isJustBound() && mCachedRawImageReady) { if(mBoostLevel < BOOST_HIGH) { // We haven't rendered this in a while, de-prioritize it desired_discard += 2; } - //else - //{ - // // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is - // desired_discard = cur_discard; - //} + else + { + // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is + desired_discard = cur_discard; + } } S32 ddiscard = cur_discard - desired_discard; - ddiscard = llclamp(ddiscard, 0, 4); - priority = (ddiscard+1)*100000.f; + ddiscard = llclamp(ddiscard, -1, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); + priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; } // Priority Formula: // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS - // [10,000,000] + [1-9,000,000] + [1-400,000] + [1-20,000] + [0-999] + // [10,000,000] + [1,000,000-9,000,000] + [100,000-500,000] + [1-20,000] + [0-999] if (priority > 0.0f) { - pixel_priority = llclamp(pixel_priority, 0.0f, 999.f); + bool large_enough = mCachedRawImageReady && ((S32)mTexelsPerImage > sMinLargeImageSize) ; + if(large_enough) + { + //Note: + //to give small, low-priority textures some chance to be fetched, + //cut the priority in half if the texture size is larger than 256 * 256 and has a 64*64 ready. + priority *= 0.5f ; + } + + pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); - priority = pixel_priority + 1000.f * mBoostLevel; + priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel; if ( mBoostLevel > BOOST_HIGH) { - priority += 10000000.f; + if(mBoostLevel > BOOST_SUPER_HIGH) + { + //for very important textures, always grant the highest priority. + priority += PRIORITY_BOOST_HIGH_FACTOR; + } + else if(mCachedRawImageReady) + { + //Note: + //to give small, low-priority textures some chance to be fetched, + //if high priority texture has a 64*64 ready, lower its fetching priority. + setAdditionalDecodePriority(0.5f) ; + } + else + { + priority += PRIORITY_BOOST_HIGH_FACTOR; + } } if(mAdditionalDecodePriority > 0.0f) { - // 1-9 - S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round - // priority range += 0-9,000,000 - priority += 1000000.f * (F32)additional_priority; + // priority range += 1,000,000.f-9,000,000.f + F32 additional = PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY); + if(large_enough) + { + //Note: + //to give small, low-priority textures some chance to be fetched, + //cut the additional priority to a quarter if the texture size is larger than 256 * 256 and has a 64*64 ready. + additional *= 0.25f ; + } + priority += additional; } } return priority; } + +//static +F32 LLViewerFetchedTexture::maxDecodePriority() +{ + static const F32 max_priority = PRIORITY_BOOST_HIGH_FACTOR + //boost_high + PRIORITY_ADDITIONAL_FACTOR * (MAX_ADDITIONAL_LEVEL_FOR_PRIORITY + 1) + //additional (view dependent factors) + PRIORITY_DELTA_DISCARD_LEVEL_FACTOR * (MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY + 1) + //delta discard + PRIORITY_BOOST_LEVEL_FACTOR * (BOOST_MAX_LEVEL - 1) + //boost level + MAX_PRIORITY_PIXEL + 1.0f ; //pixel area. + + return max_priority ; +} + //============================================================================ void LLViewerFetchedTexture::setDecodePriority(F32 priority) { - //llassert(!mInImageList); // firing a lot, figure out why - if (mInImageList) // above llassert() softened to a warning - { - llwarns << "BAD STUFF! mInImageList" << llendl; - } + llassert(!mInImageList); + mDecodePriority = priority; + + if(mDecodePriority < F_ALMOST_ZERO) + { + mStopFetchingTimer.reset() ; + } } void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) @@ -1579,7 +1740,7 @@ void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) void LLViewerFetchedTexture::updateVirtualSize() { - if(mNeedsResetMaxVirtualSize) + if(!mMaxVirtualSizeResetCounter) { addTextureStats(0.f, FALSE) ;//reset } @@ -1593,8 +1754,31 @@ void LLViewerFetchedTexture::updateVirtualSize() setAdditionalDecodePriority(facep->getImportanceToCamera()) ; } } - mNeedsResetMaxVirtualSize = TRUE ; + + if(mMaxVirtualSizeResetCounter > 0) + { + mMaxVirtualSizeResetCounter--; + } reorganizeFaceList() ; + reorganizeVolumeList(); +} + +S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() +{ + S32 current_discard = getDiscardLevel() ; + if(mForceToSaveRawImage) + { + if(mSavedRawDiscardLevel < 0 || current_discard < 0) + { + current_discard = -1 ; + } + else + { + current_discard = llmax(current_discard, mSavedRawDiscardLevel) ; + } + } + + return current_discard ; } bool LLViewerFetchedTexture::updateFetch() @@ -1633,7 +1817,7 @@ bool LLViewerFetchedTexture::updateFetch() return false; // process any raw image data in callbacks before replacing } - S32 current_discard = getDiscardLevel() ; + S32 current_discard = getCurrentDiscardLevelForFetching() ; S32 desired_discard = getDesiredDiscardLevel(); F32 decode_priority = getDecodePriority(); decode_priority = llmax(decode_priority, 0.0f); @@ -1643,14 +1827,6 @@ bool LLViewerFetchedTexture::updateFetch() // Sets mRawDiscardLevel, mRawImage, mAuxRawImage S32 fetch_discard = current_discard; - if(mForceToSaveRawImage) - { - if(fetch_discard >= 0) - { - fetch_discard = llmax(fetch_discard, mSavedRawDiscardLevel) ; - } - } - if (mRawImage.notNull()) sRawCount--; if (mAuxRawImage.notNull()) sAuxCount--; bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); @@ -1659,11 +1835,12 @@ bool LLViewerFetchedTexture::updateFetch() if (finished) { mIsFetching = FALSE; + mLastPacketTimer.reset() ; } else { mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); } // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) @@ -1678,20 +1855,9 @@ bool LLViewerFetchedTexture::updateFetch() if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) { - if (getComponents() != mRawImage->getComponents()) - { - // We've changed the number of components, so we need to move any - // objects using this pool to a different pool. - mComponents = mRawImage->getComponents(); - mGLTexturep->setComponents(mComponents) ; - - for(U32 i = 0 ; i < mNumFaces ; i++) - { - mFaceList[i]->dirtyTexture() ; - } - } mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; + setTexelsPerImage(); if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) { @@ -1700,6 +1866,7 @@ bool LLViewerFetchedTexture::updateFetch() setIsMissingAsset(); mRawDiscardLevel = INVALID_DISCARD_LEVEL ; mIsFetching = FALSE ; + mLastPacketTimer.reset(); } else { @@ -1751,19 +1918,12 @@ bool LLViewerFetchedTexture::updateFetch() // llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl; // calcDecodePriority(); // } - LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); - } - } - - if (!mDontDiscard) - { - if (mBoostLevel == 0) - { - desired_discard = llmax(desired_discard, current_discard-1); - } - else - { - desired_discard = llmax(desired_discard, current_discard-2); + 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) + { + mStopFetchingTimer.reset() ; + LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); + } } } @@ -1784,8 +1944,20 @@ bool LLViewerFetchedTexture::updateFetch() //{ // make_request = false; //} - else + + if(make_request) { + //load the texture progressively. + S32 delta_level = (mBoostLevel > LLViewerTexture::BOOST_NONE) ? 2 : 1 ; + if(current_discard < 0) + { + desired_discard = llmax(desired_discard, getMaxDiscardLevel() - delta_level); + } + else + { + desired_discard = llmax(desired_discard, current_discard - delta_level); + } + if (mIsFetching) { if (mRequestedDiscardLevel <= desired_discard) @@ -1805,17 +1977,23 @@ bool LLViewerFetchedTexture::updateFetch() if (make_request) { S32 w=0, h=0, c=0; - if (current_discard >= 0) + if (getDiscardLevel() >= 0) { w = mGLTexturep->getWidth(0); h = mGLTexturep->getHeight(0); c = mComponents; } + + const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + if (override_tex_discard_level != 0) + { + desired_discard = override_tex_discard_level; + } // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux()); + w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) { @@ -1823,7 +2001,7 @@ bool LLViewerFetchedTexture::updateFetch() mIsFetching = TRUE; mRequestedDiscardLevel = desired_discard; mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime, mCanUseHTTP); } // if createRequest() failed, we're finishing up a request for this UUID, @@ -1846,73 +2024,6 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } -// -//force to fetch a new raw image for this texture -// -BOOL LLViewerFetchedTexture::forceFetch() -{ - if(!mForceToSaveRawImage) - { - return false ; - } - //if(mDesiredSavedRawDiscardLevel < getDiscardLevel()) - { - //no need to force fetching. normal fetching flow will do the work. - //return false ; - } - //if (mNeedsCreateTexture) - { - // We may be fetching still (e.g. waiting on write) - // but don't check until we've processed the raw data we have - //return false; - } - if(mIsFetching) - { - return false ; - } - if (mIsMissingAsset) - { - mForceToSaveRawImage = false ; - llassert_always(!mHasFetcher); - return false; // skip - } - if (!mLoadedCallbackList.empty() && mRawImage.notNull()) - { - return false; // process any raw image data in callbacks before replacing - } - if(mRawImage.notNull() && mRawDiscardLevel <= mDesiredSavedRawDiscardLevel) - { - return false ; // mRawImage is enough - } - - S32 desired_discard = mDesiredSavedRawDiscardLevel ; - S32 current_discard = getDiscardLevel(); - - bool fetch_request_created = false; - S32 w=0, h=0, c=0; - if (current_discard >= 0) - { - w = getWidth(0); - h = getHeight(0); - c = getComponents(); - } - setDecodePriority(maxDecodePriority()) ; - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), getDecodePriority(), - w, h, c, desired_discard, needsAux()); - - if (fetch_request_created) - { - mHasFetcher = TRUE; - mIsFetching = TRUE; - mRequestedDiscardLevel = desired_discard ; - - mFetchState = LLAppViewer::getTextureFetch()->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, - mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); - } - - return mIsFetching ? true : false; -} - void LLViewerFetchedTexture::setIsMissingAsset() { if (mUrl.empty()) @@ -1928,6 +2039,7 @@ void LLViewerFetchedTexture::setIsMissingAsset() LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); mHasFetcher = FALSE; mIsFetching = FALSE; + mLastPacketTimer.reset(); mFetchState = 0; mFetchPriority = 0; } @@ -1935,7 +2047,8 @@ void LLViewerFetchedTexture::setIsMissingAsset() } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, - S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata) + S32 discard_level, BOOL keep_imageraw, BOOL needs_aux, void* userdata, + LLLoadedCallbackEntry::source_callback_list_t* src_callback_list, BOOL pause) { // // Don't do ANYTHING here, just add it to the global callback list @@ -1951,9 +2064,18 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ; } - LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata); - mLoadedCallbackList.push_back(entryp); + if(mPauseLoadedCallBacks && !pause) + { + unpauseLoadedCallbacks(src_callback_list) ; + } + LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata, src_callback_list, this, pause); + mLoadedCallbackList.push_back(entryp); + mNeedsAux |= needs_aux; + if(keep_imageraw) + { + forceToSaveRawImage(discard_level, true) ; + } if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) { // We need aux data, but we've already loaded the image, and it didn't have any @@ -1961,6 +2083,154 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call } } +void LLViewerFetchedTexture::clearCallbackEntryList() +{ + if(mLoadedCallbackList.empty()) + { + return ; + } + + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter; + + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); + iter = mLoadedCallbackList.erase(iter) ; + delete entryp; + } + gTextureList.mCallbackList.erase(this); + + mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + mLoadedCallbackDesiredDiscardLevel = S8_MAX ; + if(mForceToSaveRawImage) + { + destroySavedRawImage() ; + } + + return ; +} + +void LLViewerFetchedTexture::deleteCallbackEntry(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) +{ + if(mLoadedCallbackList.empty() || !callback_list) + { + return ; + } + + S32 desired_discard = S8_MAX ; + S32 desired_raw_discard = INVALID_DISCARD_LEVEL ; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter; + if(entryp->mSourceCallbackList == callback_list) + { + // We never finished loading the image. Indicate failure. + // Note: this allows mLoadedCallbackUserData to be cleaned up. + entryp->mCallback(FALSE, this, NULL, NULL, 0, TRUE, entryp->mUserData); + iter = mLoadedCallbackList.erase(iter) ; + delete entryp; + } + else + { + ++iter; + + desired_discard = llmin(desired_discard, entryp->mDesiredDiscard) ; + if(entryp->mNeedsImageRaw) + { + desired_raw_discard = llmin(desired_raw_discard, entryp->mDesiredDiscard) ; + } + } + } + + mLoadedCallbackDesiredDiscardLevel = desired_discard; + if (mLoadedCallbackList.empty()) + { + // If we have no callbacks, take us off of the image callback list. + gTextureList.mCallbackList.erase(this); + mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; + + if(mForceToSaveRawImage) + { + destroySavedRawImage() ; + } + } + else if(mForceToSaveRawImage && mBoostLevel != LLViewerTexture::BOOST_PREVIEW) + { + if(desired_raw_discard != INVALID_DISCARD_LEVEL) + { + mDesiredSavedRawDiscardLevel = desired_raw_discard ; + } + else + { + destroySavedRawImage() ; + } + } +} + +void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) +{ + if(!callback_list) +{ + mPauseLoadedCallBacks = FALSE ; + return ; + } + + BOOL need_raw = FALSE ; + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + if(entryp->mSourceCallbackList == callback_list) + { + entryp->mPaused = FALSE ; + if(entryp->mNeedsImageRaw) + { + need_raw = TRUE ; + } + } + } + mPauseLoadedCallBacks = FALSE ; + if(need_raw) + { + mForceToSaveRawImage = TRUE ; + } +} + +void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::source_callback_list_t* callback_list) +{ + if(!callback_list) +{ + return ; + } + + bool paused = true ; + + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); + iter != mLoadedCallbackList.end(); ) + { + LLLoadedCallbackEntry *entryp = *iter++; + if(entryp->mSourceCallbackList == callback_list) + { + entryp->mPaused = TRUE ; + } + else if(!entryp->mPaused) + { + paused = false ; + } + } + + if(paused) + { + mPauseLoadedCallBacks = TRUE ;//when set, loaded callback is paused. + resetTextureStats(); + mForceToSaveRawImage = FALSE ; + } +} + bool LLViewerFetchedTexture::doLoadedCallbacks() { if (mNeedsCreateTexture) @@ -1986,6 +2256,11 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // Remove ourself from the global list of textures with callbacks gTextureList.mCallbackList.erase(this); } + if(mPauseLoadedCallBacks) + { + destroyRawImage(); + return res; //paused + } S32 gl_discard = getDiscardLevel(); @@ -2027,10 +2302,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() bool run_raw_callbacks = false; bool need_readback = false; + mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { LLLoadedCallbackEntry *entryp = *iter++; + mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel, (S8)entryp->mDesiredDiscard) ; + if (entryp->mNeedsImageRaw) { if (mNeedsAux) @@ -2112,10 +2390,6 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE; //llinfos << "Running callback for " << getID() << llendl; //llinfos << mRawImage->getWidth() << "x" << mRawImage->getHeight() << llendl; - if (final) - { - //llinfos << "Final!" << llendl; - } entryp->mLastUsedDiscard = mRawDiscardLevel; entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); if (final) @@ -2162,6 +2436,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (mLoadedCallbackList.empty()) { gTextureList.mCallbackList.erase(this); + mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; } // Done with any raw image data at this point (will be re-created if we still have callbacks) @@ -2202,8 +2477,15 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; - mRawImage->copy(getSavedRawImage()) ; + if(mSavedRawDiscardLevel != discard_level) + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; + mRawImage->copy(getSavedRawImage()) ; + } + else + { + mRawImage = getSavedRawImage() ; + } mRawDiscardLevel = discard_level ; } else @@ -2213,13 +2495,18 @@ LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) { mRawImage = mCachedRawImage ; mRawDiscardLevel = mCachedRawDiscardLevel; - - forceToSaveRawImage(discard_level) ; } else //cached raw image is good enough, copy it. { - mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; - mRawImage->copy(mCachedRawImage) ; + if(mCachedRawDiscardLevel != discard_level) + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; + mRawImage->copy(mCachedRawImage) ; + } + else + { + mRawImage = mCachedRawImage ; + } mRawDiscardLevel = discard_level ; } } @@ -2235,24 +2522,22 @@ void LLViewerFetchedTexture::destroyRawImage() if (mRawImage.notNull()) { - sRawCount--; - setCachedRawImage() ; + sRawCount--; - if(mForceToSaveRawImage) + if(mIsRawImageValid) { - saveRawImage() ; - } + if(mForceToSaveRawImage) + { + saveRawImage() ; + } + setCachedRawImage() ; + } } mRawImage = NULL; mAuxRawImage = NULL; mIsRawImageValid = FALSE; mRawDiscardLevel = INVALID_DISCARD_LEVEL; - - if(mForceToSaveRawImage) - { - forceFetch() ; - } } //use the mCachedRawImage to (re)generate the gl texture. @@ -2279,6 +2564,18 @@ void LLViewerFetchedTexture::switchToCachedImage() } } +//cache the imageraw forcefully. +//virtual +void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) +{ + if(imageraw != mRawImage.get()) + { + mCachedRawImage = imageraw ; + mCachedRawDiscardLevel = discard_level ; + mCachedRawImageReady = TRUE ; + } +} + void LLViewerFetchedTexture::setCachedRawImage() { if(mRawImage == mCachedRawImage) @@ -2327,17 +2624,12 @@ void LLViewerFetchedTexture::setCachedRawImage() { --i ; } - //if(mForSculpt) - //{ - // mRawImage->scaleDownWithoutBlending(w >> i, h >> i) ; - //} - //else - { - mRawImage->scale(w >> i, h >> i) ; - } + + mRawImage->scale(w >> i, h >> i) ; } mCachedRawImage = mRawImage ; - mCachedRawDiscardLevel = mRawDiscardLevel + i ; + mRawDiscardLevel += i ; + mCachedRawDiscardLevel = mRawDiscardLevel ; } } @@ -2358,7 +2650,7 @@ void LLViewerFetchedTexture::checkCachedRawSculptImage() void LLViewerFetchedTexture::saveRawImage() { - if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel) + if(mRawImage.isNull() || mRawImage == mSavedRawImage || (mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= mRawDiscardLevel)) { return ; } @@ -2374,18 +2666,36 @@ void LLViewerFetchedTexture::saveRawImage() mLastReferencedSavedRawImageTime = sCurrentTime ; } -void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) +void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, bool from_callback) { - if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)) + if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard) { + llassert_always(from_callback || mBoostLevel == LLViewerTexture::BOOST_PREVIEW) ; + mForceToSaveRawImage = TRUE ; mDesiredSavedRawDiscardLevel = desired_discard ; - forceFetch() ; + //copy from the cached raw image if exists. + if(mCachedRawImage.notNull() && mRawImage.isNull() ) + { + mRawImage = mCachedRawImage ; + mRawDiscardLevel = mCachedRawDiscardLevel ; + + saveRawImage() ; + + mRawImage = NULL ; + mRawDiscardLevel = INVALID_DISCARD_LEVEL ; + } } } void LLViewerFetchedTexture::destroySavedRawImage() { + clearCallbackEntryList() ; + //if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0 && mDesiredSavedRawDiscardLevel < getDiscardLevel()) + //{ + // return ; //can not destroy the saved raw image before it is fully fetched, otherwise causing callbacks hanging there. + //} + mSavedRawImage = NULL ; mForceToSaveRawImage = FALSE ; mSavedRawDiscardLevel = -1 ; @@ -2407,7 +2717,7 @@ BOOL LLViewerFetchedTexture::hasSavedRawImage() const F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const { - return mLastReferencedSavedRawImageTime - sCurrentTime ; + return sCurrentTime - mLastReferencedSavedRawImageTime ; } //---------------------------------------------------------------------------------------------- //atlasing @@ -2636,7 +2946,7 @@ BOOL LLViewerLODTexture::isUpdateFrozen() void LLViewerLODTexture::processTextureStats() { updateVirtualSize() ; - + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); if (textures_fullres) @@ -2664,10 +2974,6 @@ void LLViewerLODTexture::processTextureStats() //static const F64 log_2 = log(2.0); static const F64 log_4 = log(4.0); - S32 fullwidth = llmin(mFullWidth,(S32)MAX_IMAGE_SIZE_DEFAULT); - S32 fullheight = llmin(mFullHeight,(S32)MAX_IMAGE_SIZE_DEFAULT); - mTexelsPerImage = (F32)fullwidth * fullheight; - F32 discard_level = 0.f; // If we know the output width and height, we can force the discard @@ -2684,7 +2990,7 @@ void LLViewerLODTexture::processTextureStats() } else { - if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 1.0f) + if(isLargeImage() && !isJustBound() && mAdditionalDecodePriority < 0.3f) { //if is a big image and not being used recently, nor close to the view point, do not load hi-res data. mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)LLViewerTexture::sMinLargeImageSize) ; @@ -2704,7 +3010,7 @@ void LLViewerLODTexture::processTextureStats() mCalculatedDiscardLevel = discard_level; } } - if (mBoostLevel < LLViewerTexture::BOOST_HIGH) + if (mBoostLevel < LLViewerTexture::BOOST_SCULPTED) { discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale @@ -2730,8 +3036,7 @@ void LLViewerLODTexture::processTextureStats() // S32 current_discard = getDiscardLevel(); - if ((sDesiredDiscardBias > 0.0f) && - (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) + if (sDesiredDiscardBias > 0.0f && mBoostLevel < LLViewerTexture::BOOST_SCULPTED && current_discard >= 0) { // Limit the amount of GL memory bound each frame if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale && @@ -2748,6 +3053,11 @@ void LLViewerLODTexture::processTextureStats() } } } + + if(mForceToSaveRawImage && mDesiredSavedRawDiscardLevel >= 0) + { + mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel) ; + } } void LLViewerLODTexture::scaleDown() @@ -2810,7 +3120,7 @@ void LLViewerMediaTexture::removeMediaImplFromTexture(const LLUUID& media_id) } //static -void LLViewerMediaTexture::cleanup() +void LLViewerMediaTexture::cleanUpClass() { sMediaMap.clear() ; } @@ -2870,12 +3180,11 @@ LLViewerMediaTexture::~LLViewerMediaTexture() void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) { - mGLTexturep = NULL ; - init(false); + llassert(mGLTexturep.notNull()) ; + mUseMipMaps = usemipmaps ; getLastReferencedTimer()->reset() ; - - generateGLTexture() ; + mGLTexturep->setUseMipMaps(mUseMipMaps) ; mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; } @@ -2980,6 +3289,10 @@ void LLViewerMediaTexture::initVirtualSize() void LLViewerMediaTexture::addMediaToFace(LLFace* facep) { + if(facep) + { + facep->setHasMedia(true) ; + } if(!mIsPlaying) { return ; //no need to add the face because the media is not in playing. @@ -2990,14 +3303,16 @@ void LLViewerMediaTexture::addMediaToFace(LLFace* facep) void LLViewerMediaTexture::removeMediaFromFace(LLFace* facep) { - if(!mIsPlaying) - { - return ; //no need to remove the face because the media is not in playing. - } if(!facep) { return ; } + facep->setHasMedia(false) ; + + if(!mIsPlaying) + { + return ; //no need to remove the face because the media is not in playing. + } mIsPlaying = FALSE ; //set to remove the media from the face. switchTexture(facep) ; @@ -3214,7 +3529,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() } mUpdateVirtualSizeTime = LLFrameTimer::getFrameCount() ; - if(mNeedsResetMaxVirtualSize) + if(!mMaxVirtualSizeResetCounter) { addTextureStats(0.f, FALSE) ;//reset } @@ -3247,8 +3562,12 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() } } - mNeedsResetMaxVirtualSize = TRUE ; + if(mMaxVirtualSizeResetCounter > 0) + { + mMaxVirtualSizeResetCounter--; + } reorganizeFaceList() ; + reorganizeVolumeList(); return mMaxVirtualSize ; } @@ -3429,7 +3748,7 @@ void LLTexturePipelineTester::updateStablizingTime() { F32 t = mEndStablizingTime - mStartStablizingTime ; - if(t > 0.0001f && (t - mTotalStablizingTime) < 0.0001f) + if(t > F_ALMOST_ZERO && (t - mTotalStablizingTime) < F_ALMOST_ZERO) { //already stablized mTotalStablizingTime = LLImageGL::sLastFrameTime - mStartStablizingTime ; @@ -3554,7 +3873,7 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi //time F32 start_time = (*log)[label]["StartFetchingTime"].asReal() ; F32 cur_time = (*log)[label]["Time"].asReal() ; - if(start_time - start_fetching_time > 0.0001f) //fetching has paused for a while + if(start_time - start_fetching_time > F_ALMOST_ZERO) //fetching has paused for a while { sessionp->mTotalFetchingTime += total_fetching_time ; sessionp->mTotalGrayTime += total_gray_time ; |