diff options
Diffstat (limited to 'indra/newview/llviewertexture.cpp')
-rw-r--r-- | indra/newview/llviewertexture.cpp | 1349 |
1 files changed, 1059 insertions, 290 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e5c53c91c9..6add8a7e92 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -60,6 +60,8 @@ #include "llviewercontrol.h" #include "pipeline.h" #include "llappviewer.h" +#include "llface.h" +#include "llviewercamera.h" #include "lltextureatlas.h" #include "lltextureatlasmanager.h" #include "lltextureentry.h" @@ -88,15 +90,37 @@ S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0; S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; -BOOL LLViewerTexture::sDontLoadVolumeTextures = FALSE; +S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; +S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size +const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; +const S32 MAX_CACHED_RAW_SCULPT_IMAGE_AREA = LLViewerTexture::sMaxSculptRez * LLViewerTexture::sMaxSculptRez ; +const S32 MAX_CACHED_RAW_TERRAIN_IMAGE_AREA = 128 * 128 ; +S32 LLViewerTexture::sMinLargeImageSize = 65536 ; //256 * 256. +S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; +BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; +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 F64 log_2 = log(2.0); //---------------------------------------------------------------------------------------------- //namespace: LLViewerTextureAccess //---------------------------------------------------------------------------------------------- + +LLLoadedCallbackEntry::LLLoadedCallbackEntry(loaded_callback_func cb, + S32 discard_level, + BOOL need_imageraw, // Needs image raw for the callback + void* userdata ) + : mCallback(cb), + mLastUsedDiscard(MAX_DISCARD_LEVEL+1), + mDesiredDiscard(discard_level), + mNeedsImageRaw(need_imageraw), + mUserData(userdata) +{ +} + LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &media_id, BOOL usemipmaps, LLImageGL* gl_image) { return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ; @@ -134,7 +158,7 @@ LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, return tex ; } -LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error) +LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error) { if(!tex) { @@ -161,6 +185,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(BOOL usemipma if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } @@ -170,12 +195,14 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLUUID& if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const LLImageRaw* raw, BOOL usemipmaps) { LLPointer<LLViewerTexture> tex = new LLViewerTexture(raw, usemipmaps) ; + tex->setCategory(LLViewerTexture::LOCAL) ; return tex ; } LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex) @@ -184,6 +211,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid if(generate_gl_tex) { tex->generateGLTexture() ; + tex->setCategory(LLViewerTexture::LOCAL) ; } return tex ; } @@ -191,7 +219,7 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, BOOL usemipmaps, - S32 boost_priority, + LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, @@ -203,7 +231,7 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( const std::string& filename, BOOL usemipmaps, - S32 boost_priority, + LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, LLGLint internal_format, LLGLenum primary_format, @@ -212,6 +240,19 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; } +//static +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, + BOOL usemipmaps, + LLViewerTexture::EBoostLevel boost_priority, + S8 texture_type, + LLGLint internal_format, + LLGLenum primary_format, + const LLUUID& force_id + ) +{ + return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; +} + LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) { return gTextureList.getImageFromHost(image_id, host) ; @@ -252,13 +293,16 @@ void LLViewerTextureManager::init() } } imagep->createGLTexture(0, image_raw); + //cache the raw image + imagep->setCachedRawImage(0, image_raw) ; image_raw = NULL; - LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); #else - LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE); + LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI); #endif - - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, TRUE); + LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); + LLViewerFetchedTexture::sDefaultImagep->setCategory(LLViewerTexture::OTHER) ; + + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; LLViewerTexture::initClass() ; @@ -281,6 +325,8 @@ void LLViewerTextureManager::cleanup() LLViewerFetchedTexture::sWhiteImagep = NULL; LLViewerMediaTexture::cleanup() ; + + LLViewerTexture::cleanupClass() ; } //---------------------------------------------------------------------------------------------- @@ -291,6 +337,11 @@ void LLViewerTextureManager::cleanup() void LLViewerTexture::initClass() { LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture() ; + + if(gAuditTexture) + { + LLImageGL::setHighlightTexture(LLViewerTexture::OTHER) ; + } } // static @@ -298,6 +349,25 @@ void LLViewerTexture::cleanupClass() { } +// static +S32 LLViewerTexture::getTotalNumOfCategories() +{ + return MAX_GL_IMAGE_CATEGORY - (BOOST_HIGH - BOOST_SCULPTED) + 2 ; +} + +// static +//index starts from zero. +S32 LLViewerTexture::getIndexFromCategory(S32 category) +{ + return (category < BOOST_HIGH) ? category : category - (BOOST_HIGH - BOOST_SCULPTED) + 1 ; +} + +//static +S32 LLViewerTexture::getCategoryFromIndex(S32 index) +{ + return (index < BOOST_HIGH) ? index : index + (BOOST_HIGH - BOOST_SCULPTED) - 1 ; +} + // tuning params const F32 discard_bias_delta = .05f; const F32 discard_delta_time = 0.5f; @@ -309,6 +379,8 @@ F32 texmem_middle_bound_scale = 0.925f; //static void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity) { + sCurrentTime = gFrameTimeSeconds ; + if(LLViewerTextureManager::sTesterp) { LLViewerTextureManager::sTesterp->update() ; @@ -349,6 +421,13 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max); LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; + + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); + sCameraMovingDiscardBias = (S8)llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1) ; + + LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && + (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; } //end of static functions @@ -414,7 +493,14 @@ void LLViewerTexture::init(bool firstinit) mTextureState = NO_DELETE ; mDontDiscard = FALSE; mMaxVirtualSize = 0.f; + mNeedsGLTexture = FALSE ; mNeedsResetMaxVirtualSize = FALSE ; + mAdditionalDecodePriority = 0.f ; + mParcelMedia = NULL ; + mNumFaces = 0 ; + mNumVolumes = 0; + mFaceList.clear() ; + mVolumeList.clear(); } //virtual @@ -426,7 +512,7 @@ S8 LLViewerTexture::getType() const void LLViewerTexture::cleanup() { mFaceList.clear() ; - + mVolumeList.clear(); if(mGLTexturep) { mGLTexturep->cleanup(); @@ -455,11 +541,15 @@ void LLViewerTexture::setBoostLevel(S32 level) { setNoDelete() ; } + if(gAuditTexture) + { + setCategory(mBoostLevel); + } } } -bool LLViewerTexture::bindDefaultImage(S32 stage) const +bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -478,6 +568,10 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) const llwarns << "LLViewerTexture::bindDefaultImage failed." << llendl; } stop_glerror(); + + //check if there is cached raw image and switch to it if possible + switchToCachedImage() ; + if(LLViewerTextureManager::sTesterp) { LLViewerTextureManager::sTesterp->updateGrayTextureBinding() ; @@ -496,24 +590,32 @@ void LLViewerTexture::forceImmediateUpdate() { } -void LLViewerTexture::addTextureStats(F32 virtual_size) const +void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { - if (virtual_size > mMaxVirtualSize) + if(needs_gltexture) { - mMaxVirtualSize = virtual_size; + mNeedsGLTexture = TRUE ; } -} -void LLViewerTexture::resetTextureStats(BOOL zero) -{ - if (zero) + if(mNeedsResetMaxVirtualSize) { - mMaxVirtualSize = 0.0f; + //flag to reset the values because the old values are used. + mNeedsResetMaxVirtualSize = FALSE ; + mMaxVirtualSize = virtual_size; + mAdditionalDecodePriority = 0.f ; + mNeedsGLTexture = needs_gltexture ; } - else + else if (virtual_size > mMaxVirtualSize) { - mMaxVirtualSize -= mMaxVirtualSize * .10f; // decay by 5%/update - } + mMaxVirtualSize = virtual_size; + } +} + +void LLViewerTexture::resetTextureStats() +{ + mMaxVirtualSize = 0.0f; + mAdditionalDecodePriority = 0.f ; + mNeedsResetMaxVirtualSize = FALSE ; } //virtual @@ -522,16 +624,127 @@ F32 LLViewerTexture::getMaxVirtualSize() return mMaxVirtualSize ; } +//virtual +void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) +{ + //nothing here. +} + //virtual void LLViewerTexture::addFace(LLFace* facep) { - mFaceList.push_back(facep) ; + if(mNumFaces >= mFaceList.size()) + { + mFaceList.resize(2 * mNumFaces + 1) ; + } + mFaceList[mNumFaces] = facep ; + facep->setIndexInTex(mNumFaces) ; + mNumFaces++ ; + mLastFaceListUpdateTimer.reset() ; } //virtual void LLViewerTexture::removeFace(LLFace* facep) { - mFaceList.remove(facep) ; + if(mNumFaces > 1) + { + S32 index = facep->getIndexInTex() ; + mFaceList[index] = mFaceList[--mNumFaces] ; + mFaceList[index]->setIndexInTex(index) ; + } + else + { + mFaceList.clear() ; + mNumFaces = 0 ; + } + mLastFaceListUpdateTimer.reset() ; +} + +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 + static const U32 MAX_EXTRA_BUFFER_SIZE = 4 ; + + if(mNumFaces + MAX_EXTRA_BUFFER_SIZE > mFaceList.size()) + { + return ; + } + + if(mLastFaceListUpdateTimer.getElapsedTimeF32() < MAX_WAIT_TIME) + { + return ; + } + + mLastFaceListUpdateTimer.reset() ; + 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() +{ + //nothing here. } void LLViewerTexture::forceActive() @@ -563,7 +776,7 @@ void LLViewerTexture::generateGLTexture() LLImageGL* LLViewerTexture::getGLTexture() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; return mGLTexturep ; } @@ -578,73 +791,79 @@ BOOL LLViewerTexture::createGLTexture() return mGLTexturep->createGLTexture() ; } -BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S32 usename) +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) ; + BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ; if(ret) { mFullWidth = mGLTexturep->getCurrentWidth() ; mFullHeight = mGLTexturep->getCurrentHeight() ; - mComponents = mGLTexturep->getComponents() ; + mComponents = mGLTexturep->getComponents() ; } 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() ; } @@ -669,117 +888,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(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::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_height, S32 ncomponents) +BOOL LLViewerTexture::isJustBound() const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->isValidForSculpt(discard_level, image_width, image_height, ncomponents) ; + return mGLTexturep->isJustBound() ; } -BOOL LLViewerTexture::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const +void LLViewerTexture::forceUpdateBindStats(void) const { - llassert_always(mGLTexturep.notNull()) ; + llassert(mGLTexturep.notNull()) ; - return mGLTexturep->readBackRaw(discard_level, imageraw, compressed_ok) ; + 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() ; } @@ -793,6 +1019,11 @@ void LLViewerTexture::destroyGLTexture() } } +BOOL LLViewerTexture::isLargeImage() +{ + return mFullWidth * mFullHeight > LLViewerTexture::sMinLargeImageSize ; +} + //virtual void LLViewerTexture::updateBindStatsForTester() { @@ -810,14 +1041,9 @@ void LLViewerTexture::updateBindStatsForTester() //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -//static -F32 LLViewerFetchedTexture::maxDecodePriority() -{ - return 2000000.f; -} - -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, BOOL usemipmaps) - : LLViewerTexture(id, usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) + : LLViewerTexture(id, usemipmaps), + mTargetHost(host) { init(TRUE) ; generateGLTexture() ; @@ -829,9 +1055,9 @@ LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemi init(TRUE) ; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), - mLocalFileName(full_path) + mUrl(url) { init(TRUE) ; generateGLTexture() ; @@ -852,6 +1078,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mKnownDrawWidth = 0; mKnownDrawHeight = 0; + mKnownDrawSizeChanged = FALSE ; if (firstinit) { @@ -863,6 +1090,8 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; + mLoadedCallbackDesiredDiscardLevel = 0; + mNeedsCreateTexture = FALSE; mIsRawImageValid = FALSE; @@ -875,10 +1104,19 @@ void LLViewerFetchedTexture::init(bool firstinit) mFetchPriority = 0; mDownloadProgress = 0.f; mFetchDeltaTime = 999999.f; - mDecodeFrame = 0; - mVisibleFrame = 0; + mRequestDeltaTime = 0.f; mForSculpt = FALSE ; mIsFetched = FALSE ; + + mCachedRawImage = NULL ; + mCachedRawDiscardLevel = -1 ; + mCachedRawImageReady = FALSE ; + + mSavedRawImage = NULL ; + mForceToSaveRawImage = FALSE ; + mSavedRawDiscardLevel = -1 ; + mDesiredSavedRawDiscardLevel = -1 ; + mLastReferencedSavedRawImageTime = 0.0f ; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -915,11 +1153,25 @@ void LLViewerFetchedTexture::cleanup() // Clean up image data destroyRawImage(); + mCachedRawImage = NULL ; + mCachedRawDiscardLevel = -1 ; + mCachedRawImageReady = FALSE ; + mSavedRawImage = NULL ; } void LLViewerFetchedTexture::setForSculpt() { mForSculpt = TRUE ; + if(isForSculptOnly() && !getBoundRecently()) + { + destroyGLTexture() ; //sculpt image does not need gl texture. + } + checkCachedRawSculptImage() ; +} + +BOOL LLViewerFetchedTexture::isForSculptOnly() const +{ + return mForSculpt && !mNeedsGLTexture ; } BOOL LLViewerFetchedTexture::isDeleted() @@ -954,17 +1206,37 @@ void LLViewerFetchedTexture::setInactive() } } +BOOL LLViewerFetchedTexture::isFullyLoaded() const +{ + // Unfortunately, the boolean "mFullyLoaded" is never updated correctly so we use that logic + // to check if the texture is there and completely downloaded + return (mFullWidth != 0) && (mFullHeight != 0) && !mIsFetching && !mHasFetcher; +} + + // virtual void LLViewerFetchedTexture::dump() { LLViewerTexture::dump(); - llinfos << "LLViewerFetchedTexture" - << " mIsMissingAsset " << (S32)mIsMissingAsset - << " mFullWidth " << mFullWidth - << " mFullHeight " << mFullHeight - << " mOrigWidth" << mOrigWidth - << " mOrigHeight" << mOrigHeight + llinfos << "Dump : " << mID + << ", mIsMissingAsset = " << (S32)mIsMissingAsset + << ", mFullWidth = " << (S32)mFullWidth + << ", mFullHeight = " << (S32)mFullHeight + << ", mOrigWidth = " << (S32)mOrigWidth + << ", mOrigHeight = " << (S32)mOrigHeight + << llendl; + llinfos << " : " + << " mFullyLoaded = " << (S32)mFullyLoaded + << ", mFetchState = " << (S32)mFetchState + << ", mFetchPriority = " << (S32)mFetchPriority + << ", mDownloadProgress = " << (F32)mDownloadProgress + << llendl; + llinfos << " : " + << " mHasFetcher = " << (S32)mHasFetcher + << ", mIsFetching = " << (S32)mIsFetching + << ", mIsFetched = " << (S32)mIsFetched + << ", mBoostLevel = " << (S32)mBoostLevel << llendl; } @@ -985,6 +1257,75 @@ void LLViewerFetchedTexture::destroyTexture() mFullyLoaded = FALSE ; } +// +//do not change the discard level of the loaded texture image. +BOOL LLViewerFetchedTexture::keepReuestedDiscardLevel() +{ + if (!mLoadedCallbackList.empty()) + { + return TRUE ; + } + + return FALSE ; +} + +void LLViewerFetchedTexture::addToCreateTexture() +{ + if(isForSculptOnly()) + { + //just update some variables, not to create a real GL texture. + createGLTexture(mRawDiscardLevel, mRawImage, 0, FALSE) ; + mNeedsCreateTexture = FALSE ; + destroyRawImage(); + } + else + { +#if 1 + // + //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, + //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()) + { + S32 w = mFullWidth >> mRawDiscardLevel; + S32 h = mFullHeight >> mRawDiscardLevel; + + //if big image, do not load extra data + //scale it down to size >= LLViewerTexture::sMinLargeImageSize + if(w * h > LLViewerTexture::sMinLargeImageSize) + { + S32 d_level = llmin(mRequestedDiscardLevel, (S32)mDesiredDiscardLevel) - mRawDiscardLevel ; + + if(d_level > 0) + { + S32 i = 0 ; + while((d_level > 0) && ((w >> i) * (h >> i) > LLViewerTexture::sMinLargeImageSize)) + { + i++; + d_level--; + } + if(i > 0) + { + mRawDiscardLevel += i ; + if(mRawDiscardLevel >= getDiscardLevel() && getDiscardLevel() > 0) + { + mNeedsCreateTexture = FALSE ; + destroyRawImage(); + return ; + } + mRawImage->scale(w >> i, h >> i) ; + } + } + } + } +#endif + mNeedsCreateTexture = TRUE; + gTextureList.mCreateTextureList.insert(this); + } + return ; +} + // ONLY called from LLViewerTextureList BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) { @@ -1006,7 +1347,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) if (!gNoRender) { // store original size only for locally-sourced images - if (!mLocalFileName.empty()) + if (mUrl.compare(0, 7, "file://") == 0) { mOrigWidth = mRawImage->getWidth(); mOrigHeight = mRawImage->getHeight(); @@ -1052,7 +1393,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) if(!(res = insertToAtlas())) { - res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename); + res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); resetFaceAtlas() ; } setActive() ; @@ -1084,10 +1425,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) } // Call with 0,0 to turn this feature off. +//virtual void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height) { - mKnownDrawWidth = width; - mKnownDrawHeight = height; + if(mKnownDrawWidth != width || mKnownDrawHeight != height) + { + mKnownDrawWidth = width; + mKnownDrawHeight = height; + + mKnownDrawSizeChanged = TRUE ; + mFullyLoaded = FALSE ; + } addTextureStats((F32)(width * height)); } @@ -1099,18 +1447,39 @@ void LLViewerFetchedTexture::processTextureStats() return ; } - if(!mFullWidth || !mFullHeight) + updateVirtualSize() ; + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } + else if(!mFullWidth || !mFullHeight) { mDesiredDiscardLevel = getMaxDiscardLevel() ; } else - { - mDesiredDiscardLevel = 0; - if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) + { + 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 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)) { mFullyLoaded = TRUE ; @@ -1118,18 +1487,13 @@ void LLViewerFetchedTexture::processTextureStats() } } -//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. -F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority) -{ - 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 + 1; - ddiscard = llclamp(ddiscard, 1, 9); - - return ddiscard*100000.f; -} - +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 @@ -1148,28 +1512,34 @@ F32 LLViewerFetchedTexture::calcDecodePriority() { return mDecodePriority; // no change while waiting to create } - - F32 priority; - S32 cur_discard = getDiscardLevel(); - bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); - F32 pixel_priority = fsqrtf(mMaxVirtualSize); - const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame - mDecodeFrame++; - if (pixel_priority > 0.f) + if(mForceToSaveRawImage) { - mVisibleFrame = mDecodeFrame; + return maxDecodePriority() ; } + S32 cur_discard = getDiscardLevel(); + bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); + F32 pixel_priority = fsqrtf(mMaxVirtualSize); + + F32 priority = 0.f; if (mIsMissingAsset) { priority = 0.0f; } + else if(mDesiredDiscardLevel >= cur_discard && cur_discard > -1) + { + priority = -1.0f ; + } + else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) + { + priority = -1.0f; + } else if (mDesiredDiscardLevel > getMaxDiscardLevel()) { // Don't decode anything we don't need priority = -1.0f; } - else if (mBoostLevel == LLViewerTexture::BOOST_UI && !have_all_data) + else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data) { priority = 1.f; } @@ -1181,11 +1551,6 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Always want high boosted images priority = 1.f; } - else if (mVisibleFrame == 0 || (mDecodeFrame - mVisibleFrame > MIN_NOT_VISIBLE_FRAMES)) - { - // Don't decode anything that isn't visible unless it's important - priority = -2.0f; - } else { // Leave the priority as-is @@ -1194,7 +1559,13 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else if (cur_discard < 0) { - priority = calcDecodePriorityForUnknownTexture(pixel_priority) ; + //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. + // priority range = 100,000 - 500,000 + 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, MAX_DELTA_DISCARD_LEVEL_FOR_PRIORITY); + priority = (ddiscard + 1) * PRIORITY_DELTA_DISCARD_LEVEL_FACTOR; } else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) { @@ -1207,43 +1578,116 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else { - // priority range = 100000-400000 - S32 ddiscard = cur_discard - mDesiredDiscardLevel; + // priority range = 100,000 - 500,000 + S32 desired_discard = mDesiredDiscardLevel; if (getDontDiscard()) { - ddiscard+=2; + desired_discard -= 2; } - else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == 0) + else if (!isJustBound() && mCachedRawImageReady) { - ddiscard-=2; + //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; + } } - ddiscard = llclamp(ddiscard, 0, 4); - priority = ddiscard*100000.f; + + S32 ddiscard = cur_discard - desired_discard; + ddiscard = llclamp(ddiscard, 0, 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,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, priority-1.f); // priority range = 100000-900000 + pixel_priority = llclamp(pixel_priority, 0.0f, MAX_PRIORITY_PIXEL); + + priority += pixel_priority + PRIORITY_BOOST_LEVEL_FACTOR * mBoostLevel; + if ( mBoostLevel > BOOST_HIGH) { - priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel; - } - else + priority += PRIORITY_BOOST_HIGH_FACTOR; + } + + if(mAdditionalDecodePriority > 0.0f) { - priority += 0.f + pixel_priority + 1000.f * mBoostLevel; + // priority range += 1,000,000.f-9,000,000.f + priority += PRIORITY_ADDITIONAL_FACTOR * (1.0 + mAdditionalDecodePriority * MAX_ADDITIONAL_LEVEL_FOR_PRIORITY); } } 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); + //llassert(!mInImageList); // firing a lot, figure out why + if (mInImageList) // above llassert() softened to a warning + { + llwarns << "BAD STUFF! mInImageList" << llendl; + } mDecodePriority = priority; } +void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) +{ + priority = llclamp(priority, 0.f, 1.f); + if(mAdditionalDecodePriority < priority) + { + mAdditionalDecodePriority = priority; + } +} + +void LLViewerFetchedTexture::updateVirtualSize() +{ + if(mNeedsResetMaxVirtualSize) + { + addTextureStats(0.f, FALSE) ;//reset + } + + for(U32 i = 0 ; i < mNumFaces ; i++) + { + LLFace* facep = mFaceList[i] ; + if(facep->getDrawable()->isRecentlyVisible()) + { + addTextureStats(facep->getVirtualSize()) ; + setAdditionalDecodePriority(facep->getImportanceToCamera()) ; + } + } + mNeedsResetMaxVirtualSize = TRUE ; + reorganizeFaceList() ; + reorganizeVolumeList(); +} + bool LLViewerFetchedTexture::updateFetch() { + static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); + if(textures_decode_disabled) + { + return false ; + } + mFetchState = 0; mFetchPriority = 0; mFetchDeltaTime = 999999.f; @@ -1276,11 +1720,20 @@ bool LLViewerFetchedTexture::updateFetch() S32 desired_discard = getDesiredDiscardLevel(); F32 decode_priority = getDecodePriority(); decode_priority = llmax(decode_priority, 0.0f); - + if (mIsFetching) { // 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); @@ -1315,16 +1768,29 @@ bool LLViewerFetchedTexture::updateFetch() mComponents = mRawImage->getComponents(); mGLTexturep->setComponents(mComponents) ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - (*iter)->dirtyTexture() ; + mFaceList[i]->dirtyTexture() ; } } - mIsRawImageValid = TRUE; - gTextureList.mCreateTextureList.insert(this); - mNeedsCreateTexture = TRUE; mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; + + if(mFullWidth > MAX_IMAGE_SIZE || mFullHeight > MAX_IMAGE_SIZE) + { + //discard all oversized textures. + destroyRawImage(); + setIsMissingAsset(); + mRawDiscardLevel = INVALID_DISCARD_LEVEL ; + mIsFetching = FALSE ; + } + else + { + mIsRawImageValid = TRUE; + addToCreateTexture() ; + } + + return TRUE ; } else { @@ -1347,13 +1813,13 @@ bool LLViewerFetchedTexture::updateFetch() } else { - llwarns << mID << ": Setting min discard to " << current_discard << llendl; + //llwarns << mID << ": Setting min discard to " << current_discard << llendl; mMinDiscardLevel = current_discard; desired_discard = current_discard; } destroyRawImage(); } - else if (mRawImage.isNull()) + 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 @@ -1362,12 +1828,29 @@ bool LLViewerFetchedTexture::updateFetch() } else { +// // Useful debugging code for undesired deprioritization of textures. +// if (decode_priority <= 0.0f && desired_discard >= 0 && desired_discard < current_discard) +// { +// llinfos << "Calling updateRequestPriority() with decode_priority = 0.0f" << llendl; +// calcDecodePriority(); +// } LLAppViewer::getTextureFetch()->updateRequestPriority(mID, decode_priority); } } - bool make_request = true; - + if (!mDontDiscard) + { + if (mBoostLevel == 0) + { + desired_discard = llmax(desired_discard, current_discard-1); + } + else + { + desired_discard = llmax(desired_discard, current_discard-2); + } + } + + bool make_request = true; if (decode_priority <= 0) { make_request = false; @@ -1380,6 +1863,10 @@ bool LLViewerFetchedTexture::updateFetch() { make_request = false; } + //else if (!isJustBound() && mCachedRawImageReady) + //{ + // make_request = false; + //} else { if (mIsFetching) @@ -1407,33 +1894,12 @@ bool LLViewerFetchedTexture::updateFetch() h = mGLTexturep->getHeight(0); c = mComponents; } - if (!mDontDiscard) - { - if (mBoostLevel == 0) - { - desired_discard = llmax(desired_discard, current_discard-1); - } - else - { - desired_discard = llmax(desired_discard, current_discard-2); - } - } - + // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - if (mLocalFileName.empty()) - { - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, - needsAux()); - } - else - { - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mLocalFileName, getID(),getTargetHost(), decode_priority, - w, h, c, desired_discard, - needsAux()); - } - + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, + w, h, c, desired_discard, needsAux()); + if (fetch_request_created) { mHasFetcher = TRUE; @@ -1463,9 +1929,83 @@ 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() { - llwarns << mLocalFileName << " " << mID << ": Marking image as missing" << llendl; + if (mUrl.empty()) + { + llwarns << mID << ": Marking image as missing" << llendl; + } + else + { + llwarns << mUrl << ": Marking image as missing" << llendl; + } if (mHasFetcher) { LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); @@ -1487,7 +2027,13 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call { // Put in list to call this->doLoadedCallbacks() periodically gTextureList.mCallbackList.insert(this); + mLoadedCallbackDesiredDiscardLevel = (S8)discard_level; } + else + { + mLoadedCallbackDesiredDiscardLevel = llmin(mLoadedCallbackDesiredDiscardLevel, (S8)discard_level) ; + } + LLLoadedCallbackEntry* entryp = new LLLoadedCallbackEntry(loaded_callback, discard_level, keep_imageraw, userdata); mLoadedCallbackList.push_back(entryp); mNeedsAux |= needs_aux; @@ -1616,7 +2162,7 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() // We have GL data. destroyRawImage(); - readBackRawImage(gl_discard); + reloadRawImage(mLoadedCallbackDesiredDiscardLevel); llassert_always(mRawImage.notNull()); llassert_always(!mNeedsAux || mAuxRawImage.notNull()); } @@ -1725,36 +2271,234 @@ void LLViewerFetchedTexture::forceImmediateUpdate() return ; } -// Was in LLImageGL -LLImageRaw* LLViewerFetchedTexture::readBackRawImage(S8 discard_level) +LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level) { llassert_always(mGLTexturep.notNull()) ; llassert_always(discard_level >= 0); llassert_always(mComponents > 0); + if (mRawImage.notNull()) { - llerrs << "called with existing mRawImage" << llendl; - mRawImage = NULL; + //mRawImage is in use by somebody else, do not delete it. + return NULL ; } - mRawImage = new LLImageRaw(mGLTexturep->getWidth(discard_level), mGLTexturep->getHeight(discard_level), mComponents); - sRawCount++; - mRawDiscardLevel = discard_level; - mGLTexturep->readBackRaw(mRawDiscardLevel, mRawImage, false); - mIsRawImageValid = TRUE; + + if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level) + { + mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents()) ; + mRawImage->copy(getSavedRawImage()) ; + mRawDiscardLevel = discard_level ; + } + else + { + //force to fetch raw image again if cached raw image is not good enough. + if(mCachedRawDiscardLevel > 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) ; + mRawDiscardLevel = discard_level ; + } + } + mIsRawImageValid = TRUE ; + sRawCount++; return mRawImage; } void LLViewerFetchedTexture::destroyRawImage() -{ - if (mRawImage.notNull()) sRawCount--; +{ if (mAuxRawImage.notNull()) sAuxCount--; + + if (mRawImage.notNull()) + { + sRawCount--; + + 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. +//virtual +void LLViewerFetchedTexture::switchToCachedImage() +{ + if(mCachedRawImage.notNull()) + { + mRawImage = mCachedRawImage ; + + 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) ; + gTextureList.dirtyImage(this); + } + + mIsRawImageValid = TRUE; + mRawDiscardLevel = mCachedRawDiscardLevel ; + gTextureList.mCreateTextureList.insert(this); + mNeedsCreateTexture = TRUE; + } +} + +//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) + { + return ; + } + if(!mIsRawImageValid) + { + return ; + } + + if(mCachedRawImageReady) + { + return ; + } + + if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel) + { + S32 i = 0 ; + S32 w = mRawImage->getWidth() ; + S32 h = mRawImage->getHeight() ; + + S32 max_size = MAX_CACHED_RAW_IMAGE_AREA ; + if(LLViewerTexture::BOOST_TERRAIN == mBoostLevel) + { + max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA ; + } + if(mForSculpt) + { + max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA ; + mCachedRawImageReady = !mRawDiscardLevel ; + } + else + { + mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size)) ; + } + + while(((w >> i) * (h >> i)) > max_size) + { + ++i ; + } + + if(i) + { + if(!(w >> i) || !(h >> i)) + { + --i ; + } + + mRawImage->scale(w >> i, h >> i) ; + } + mCachedRawImage = mRawImage ; + mRawDiscardLevel += i ; + mCachedRawDiscardLevel = mRawDiscardLevel ; + } +} + +void LLViewerFetchedTexture::checkCachedRawSculptImage() +{ + if(mCachedRawImageReady && mCachedRawDiscardLevel > 0) + { + if(getDiscardLevel() != 0) + { + mCachedRawImageReady = FALSE ; + } + else if(isForSculptOnly()) + { + resetTextureStats() ; //do not update this image any more. + } + } +} + +void LLViewerFetchedTexture::saveRawImage() +{ + if(mRawImage.isNull() || mSavedRawDiscardLevel == mRawDiscardLevel) + { + return ; + } + + mSavedRawDiscardLevel = mRawDiscardLevel ; + mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents()) ; + + if(mSavedRawDiscardLevel <= mDesiredSavedRawDiscardLevel) + { + mForceToSaveRawImage = FALSE ; + } + + mLastReferencedSavedRawImageTime = sCurrentTime ; +} + +void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) +{ + if(!mForceToSaveRawImage && (mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard)) + { + mForceToSaveRawImage = TRUE ; + mDesiredSavedRawDiscardLevel = desired_discard ; + + forceFetch() ; + } +} +void LLViewerFetchedTexture::destroySavedRawImage() +{ + mSavedRawImage = NULL ; + mForceToSaveRawImage = FALSE ; + mSavedRawDiscardLevel = -1 ; + mDesiredSavedRawDiscardLevel = -1 ; + mLastReferencedSavedRawImageTime = 0.0f ; } +LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() +{ + mLastReferencedSavedRawImageTime = sCurrentTime ; + + return mSavedRawImage ; +} + +BOOL LLViewerFetchedTexture::hasSavedRawImage() const +{ + return mSavedRawImage.notNull() ; +} + +F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const +{ + return sCurrentTime - mLastReferencedSavedRawImageTime ; +} //---------------------------------------------------------------------------------------------- //atlasing //---------------------------------------------------------------------------------------------- @@ -1766,16 +2510,13 @@ void LLViewerFetchedTexture::resetFaceAtlas() //invalidate all atlas slots for this image. void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom) { - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - if(*iter) + LLFace* facep = mFaceList[i] ; + facep->removeAtlas() ; + if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) { - LLFace* facep = (LLFace*)*iter ; - facep->removeAtlas() ; - if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup()) - { - facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); - } + facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY); } } } @@ -1786,7 +2527,7 @@ BOOL LLViewerFetchedTexture::insertToAtlas() { return FALSE ; } - if(mFaceList.size() < 1) + if(getNumFaces() < 1) { return FALSE ; } @@ -1810,12 +2551,10 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //if the atlas slot pointers for some faces are null, process them later. ll_face_list_t waiting_list ; - - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) { - if(*iter) { - facep = (LLFace*)*iter ; + facep = mFaceList[i] ; //face can not use atlas. if(!facep->canUseAtlas()) @@ -1952,14 +2691,14 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //---------------------------------------------------------------------------------------------- //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- -LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) + : LLViewerFetchedTexture(id, host, usemipmaps) { init(TRUE) ; } -LLViewerLODTexture::LLViewerLODTexture(const std::string& full_path, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(full_path, id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) + : LLViewerFetchedTexture(url, id, usemipmaps) { init(TRUE) ; } @@ -1977,12 +2716,25 @@ S8 LLViewerLODTexture::getType() const return LLViewerTexture::LOD_TEXTURE ; } +BOOL LLViewerLODTexture::isUpdateFrozen() +{ + return LLViewerTexture::sFreezeImageScalingDown && !getDiscardLevel() ; +} + // This is gauranteed to get called periodically for every texture //virtual void LLViewerLODTexture::processTextureStats() { + updateVirtualSize() ; + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); + + if (textures_fullres) + { + mDesiredDiscardLevel = 0; + } // Generate the request priority and render priority - if (mDontDiscard || !mUseMipMaps) + else if (mDontDiscard || !mUseMipMaps) { mDesiredDiscardLevel = 0; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -2011,13 +2763,7 @@ void LLViewerLODTexture::processTextureStats() // If we know the output width and height, we can force the discard // level to the correct value, and thus not decode more texture // data than we need to. - /*if (mBoostLevel == LLViewerTexture::BOOST_UI || - mBoostLevel == LLViewerTexture::BOOST_PREVIEW || - mBoostLevel == LLViewerTexture::BOOST_AVATAR_SELF) // what about AVATAR_BAKED_SELF? - { - discard_level = 0; // full res - } - else*/ if (mKnownDrawWidth && mKnownDrawHeight) + if (mKnownDrawWidth && mKnownDrawHeight) { S32 draw_texels = mKnownDrawWidth * mKnownDrawHeight; @@ -2028,6 +2774,12 @@ void LLViewerLODTexture::processTextureStats() } else { + 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) ; + } + if ((mCalculatedDiscardLevel >= 0.f) && (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) { @@ -2044,13 +2796,11 @@ void LLViewerLODTexture::processTextureStats() } if (mBoostLevel < LLViewerTexture::BOOST_HIGH) { - static const F32 discard_bias = -.5f; // Must be < 1 or highest discard will never load! - discard_level += discard_bias; discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale + discard_level += sCameraMovingDiscardBias ; } discard_level = floorf(discard_level); -// discard_level -= (gTextureList.mVideoMemorySetting>>1); // more video ram = higher detail F32 min_discard = 0.f; if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT) @@ -2069,46 +2819,39 @@ void LLViewerLODTexture::processTextureStats() // proper action if we don't. // - BOOL increase_discard = FALSE; S32 current_discard = getDiscardLevel(); if ((sDesiredDiscardBias > 0.0f) && (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) { - if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) - { - // Limit the amount of GL memory bound each frame - if (mDesiredDiscardLevel > current_discard) - { - increase_discard = TRUE; - } - } - if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale) + // Limit the amount of GL memory bound each frame + if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - // Only allow GL to have 2x the video card memory - if (!mGLTexturep->getBoundRecently()) - { - increase_discard = TRUE; - } + scaleDown() ; } - if (increase_discard) + // Only allow GL to have 2x the video card memory + else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale && + (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { - // llinfos << "DISCARDED: " << mID << " Discard: " << current_discard << llendl; - sBoundTextureMemoryInBytes -= mGLTexturep->mTextureMemory; - sTotalTextureMemoryInBytes -= mGLTexturep->mTextureMemory; - // Increase the discard level (reduce the texture res) - S32 new_discard = current_discard+1; - mGLTexturep->setDiscardLevel(new_discard); - sBoundTextureMemoryInBytes += mGLTexturep->mTextureMemory; - sTotalTextureMemoryInBytes += mGLTexturep->mTextureMemory; - if(LLViewerTextureManager::sTesterp) - { - LLViewerTextureManager::sTesterp->setStablizingTime() ; - } + scaleDown() ; + } } } } +void LLViewerLODTexture::scaleDown() +{ + if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel()) + { + switchToCachedImage() ; + + if(LLViewerTextureManager::sTesterp) + { + LLViewerTextureManager::sTesterp->setStablizingTime() ; + } + } +} //---------------------------------------------------------------------------------------------- //end of LLViewerLODTexture //---------------------------------------------------------------------------------------------- @@ -2121,22 +2864,28 @@ void LLViewerMediaTexture::updateClass() { static const F32 MAX_INACTIVE_TIME = 30.f ; +#if 0 + //force to play media. + gSavedSettings.setBOOL("AudioStreamingMedia", true) ; +#endif + for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); ) { LLViewerMediaTexture* mediap = iter->second; - - // - //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. - // - if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap - { - media_map_t::iterator cur = iter++ ; - sMediaMap.erase(cur) ; - } - else + + if(mediap->getNumRefs() == 1) //one reference by sMediaMap { - ++iter ; + // + //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture. + // + if(mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + { + media_map_t::iterator cur = iter++ ; + sMediaMap.erase(cur) ; + continue ; + } } + ++iter ; } } @@ -2189,21 +2938,33 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL mIsPlaying = FALSE ; setMediaImpl() ; + + setCategory(LLViewerTexture::MEDIA) ; + + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(this) ; + } } //virtual LLViewerMediaTexture::~LLViewerMediaTexture() { + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) //this media is a parcel media for tex. + { + tex->setParcelMedia(NULL) ; + } } void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) { - mGLTexturep = NULL ; - init(false); + llassert(mGLTexturep.notNull()) ; + mUseMipMaps = usemipmaps ; getLastReferencedTimer()->reset() ; - - generateGLTexture() ; + mGLTexturep->setUseMipMaps(mUseMipMaps) ; mGLTexturep->setNeedsAlphaAndPickMask(FALSE) ; } @@ -2244,15 +3005,15 @@ BOOL LLViewerMediaTexture::findFaces() mMediaFaceList.clear() ; BOOL ret = TRUE ; - - //for parcel media - LLViewerTexture* tex = gTextureList.findImage(mID) ; - if(tex) + + LLViewerTexture* tex = gTextureList.findImage(mID) ; + if(tex) //this media is a parcel media for tex. { const ll_face_list_t* face_list = tex->getFaceList() ; - for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter) + U32 end = tex->getNumFaces() ; + for(U32 i = 0 ; i < end ; i++) { - mMediaFaceList.push_back(*iter) ; + mMediaFaceList.push_back((*face_list)[i]) ; } } @@ -2274,7 +3035,8 @@ BOOL LLViewerMediaTexture::findFaces() } S32 face_id = -1 ; - while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1) + S32 num_faces = obj->mDrawable->getNumFaces() ; + while((face_id = obj->getFaceIndexWithMediaImpl(mMediaImplp, face_id)) > -1 && face_id < num_faces) { LLFace* facep = obj->mDrawable->getFace(face_id) ; if(facep) @@ -2307,6 +3069,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. @@ -2317,20 +3083,22 @@ 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) ; mIsPlaying = TRUE ; //set the flag back. - if(mFaceList.empty()) //no face referencing to this media + if(getNumFaces() < 1) //no face referencing to this media { stopPlaying() ; } @@ -2342,7 +3110,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep) LLViewerTexture::addFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -2358,8 +3126,11 @@ void LLViewerMediaTexture::addFace(LLFace* facep) mTextureList.push_back(facep->getTexture()) ; //a parcel media. return ; } - - llerrs << "The face does not have a valid texture before media texture." << llendl ; + + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "The face does not have a valid texture before media texture." << llendl ; + } } //virtual @@ -2368,7 +3139,7 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) LLViewerTexture::removeFace(facep) ; const LLTextureEntry* te = facep->getTextureEntry() ; - if(te) + if(te && te->getID().notNull()) { LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; if(tex) @@ -2386,17 +3157,17 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) // //we have some trouble here: the texture of the face is changed. //we need to find the former texture, and remove it from the list to avoid memory leaking. - if(mFaceList.empty()) + if(!mNumFaces) { mTextureList.clear() ; return ; } - S32 end = mFaceList.size() ; + S32 end = getNumFaces() ; std::vector<const LLTextureEntry*> te_list(end) ; S32 i = 0 ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 j = 0 ; j < mNumFaces ; j++) { - te_list[i++] = (*iter)->getTextureEntry() ;//all textures are in use. + te_list[i++] = mFaceList[j]->getTextureEntry() ;//all textures are in use. } for(std::list< LLPointer<LLViewerTexture> >::iterator iter = mTextureList.begin(); iter != mTextureList.end(); ++iter) @@ -2429,7 +3200,10 @@ void LLViewerMediaTexture::removeFace(LLFace* facep) } } - llerrs << "mTextureList texture reference number is corrupted." << llendl ; + if(te && te->getID().notNull()) //should have a texture + { + llerrs << "mTextureList texture reference number is corrupted." << llendl ; + } } void LLViewerMediaTexture::stopPlaying() @@ -2465,11 +3239,15 @@ void LLViewerMediaTexture::switchTexture(LLFace* facep) const LLTextureEntry* te = facep->getTextureEntry() ; if(te) { - LLViewerTexture* tex = gTextureList.findImage(te->getID()) ; + LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ; if(!tex && te->getID() != mID)//try parcel media. { tex = gTextureList.findImage(mID) ; } + if(!tex) + { + tex = LLViewerFetchedTexture::sDefaultImagep ; + } facep->switchTexture(tex) ; } } @@ -2514,16 +3292,9 @@ void LLViewerMediaTexture::setPlaying(BOOL playing) } else //stop playing this media { - if(mFaceList.empty()) + for(U32 i = mNumFaces ; i ; i--) { - return ; - } - - ll_face_list_t::iterator cur ; - for(ll_face_list_t::iterator iter = mFaceList.begin(); iter!= mFaceList.end(); ) - { - cur = iter++ ; - switchTexture(*cur) ; //cur could be removed in this function. + switchTexture(mFaceList[i - 1]) ; //current face could be removed in this function. } } return ; @@ -2540,23 +3311,19 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() if(mNeedsResetMaxVirtualSize) { - mMaxVirtualSize = 0.f ;//reset - mNeedsResetMaxVirtualSize = FALSE ; + addTextureStats(0.f, FALSE) ;//reset } if(mIsPlaying) //media is playing { - if(mFaceList.size() > 0) - { - for(std::list<LLFace*>::iterator iter = mFaceList.begin(); iter != mFaceList.end(); ++iter) + for(U32 i = 0 ; i < mNumFaces ; i++) + { + LLFace* facep = mFaceList[i] ; + if(facep->getDrawable()->isRecentlyVisible()) { - LLFace* facep = *iter ; - if(facep->getDrawable()->isRecentlyVisible()) - { - addTextureStats(facep->getVirtualSize()) ; - } - } - } + addTextureStats(facep->getVirtualSize()) ; + } + } } else //media is not in playing { @@ -2576,6 +3343,8 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() } mNeedsResetMaxVirtualSize = TRUE ; + reorganizeFaceList() ; + reorganizeVolumeList(); return mMaxVirtualSize ; } @@ -2724,7 +3493,7 @@ void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTex mTotalBytesLoadedForLargeImage += data_size ; } - if(imagep->isForSculpt()) + if(imagep->forSculpt()) { mTotalBytesLoadedForSculpties += data_size ; |