diff options
Diffstat (limited to 'indra/newview/llviewertexture.cpp')
-rw-r--r-- | indra/newview/llviewertexture.cpp | 389 |
1 files changed, 257 insertions, 132 deletions
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ca01bb46aa..e3ac56d0d3 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -39,8 +39,6 @@ #include "llimagej2c.h" #include "llimagetga.h" #include "llstl.h" -#include "llvfile.h" -#include "llvfs.h" #include "message.h" #include "lltimer.h" @@ -184,6 +182,7 @@ void LLViewerTextureManager::findFetchedTextures(const LLUUID& id, std::vector<L void LLViewerTextureManager::findTextures(const LLUUID& id, std::vector<LLViewerTexture*> &output) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; std::vector<LLViewerFetchedTexture*> fetched_output; gTextureList.findTexturesByID(id, fetched_output); std::vector<LLViewerFetchedTexture*>::iterator iter = fetched_output.begin(); @@ -208,6 +207,7 @@ void LLViewerTextureManager::findTextures(const LLUUID& id, std::vector<LLViewe LLViewerFetchedTexture* LLViewerTextureManager::findFetchedTexture(const LLUUID& id, S32 tex_type) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; return gTextureList.findImage(id, (ETexListType)tex_type); } @@ -479,11 +479,10 @@ const F32 GPU_MEMORY_CHECK_WAIT_TIME = 1.0f; F32 texmem_lower_bound_scale = 0.85f; F32 texmem_middle_bound_scale = 0.925f; -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_MEMORY_CHECK("Memory Check"); - //static bool LLViewerTexture::isMemoryForTextureLow() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // Note: we need to figure out a better source for 'min' values, // what is free for low end at minimal settings is 'nothing left' // for higher end gpus at high settings. @@ -500,6 +499,7 @@ bool LLViewerTexture::isMemoryForTextureLow() //static bool LLViewerTexture::isMemoryForTextureSuficientlyFree() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; const S32Megabytes DESIRED_FREE_TEXTURE_MEMORY(50); const S32Megabytes DESIRED_FREE_MAIN_MEMORY(200); @@ -513,10 +513,12 @@ bool LLViewerTexture::isMemoryForTextureSuficientlyFree() //static void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &physical) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLFrameTimer timer; + static S32Megabytes gpu_res = S32Megabytes(S32_MAX); static S32Megabytes physical_res = S32Megabytes(S32_MAX); - + if (timer.getElapsedTimeF32() < GPU_MEMORY_CHECK_WAIT_TIME) //call this once per second. { gpu = gpu_res; @@ -525,48 +527,31 @@ void LLViewerTexture::getGPUMemoryForTextures(S32Megabytes &gpu, S32Megabytes &p } timer.reset(); - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_MEMORY_CHECK); - - if (gGLManager.mHasATIMemInfo) { - S32 meminfo[4]; - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - gpu_res = (S32Megabytes)meminfo[0]; - + gpu_res = (S32Megabytes) LLImageGLThread::getFreeVRAMMegabytes(); + //check main memory, only works for windows. LLMemory::updateMemoryInfo(); physical_res = LLMemory::getAvailableMemKB(); - } - else if (gGLManager.mHasNVXMemInfo) - { - S32 free_memory; - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); - gpu_res = (S32Megabytes)(free_memory / 1024); - } - gpu = gpu_res; - physical = physical_res; + gpu = gpu_res; + physical = physical_res; + } } -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_MEDIA("Media"); -static LLTrace::BlockTimerStatHandle FTM_TEXTURE_UPDATE_TEST("Test"); - //static -void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity) +void LLViewerTexture::updateClass() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; sCurrentTime = gFrameTimeSeconds; LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_TEST); tester->update(); } - { - LL_RECORD_BLOCK_TIME(FTM_TEXTURE_UPDATE_MEDIA); - LLViewerMediaTexture::updateClass(); - } + LLViewerMediaTexture::updateClass(); sBoundTextureMemory = LLImageGL::sBoundTextureMemory; sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; @@ -682,6 +667,9 @@ void LLViewerTexture::init(bool firstinit) mVolumeList[LLRender::LIGHT_TEX].clear(); mVolumeList[LLRender::SCULPT_TEX].clear(); + + mMainQueue = LL::WorkQueue::getInstance("mainloop"); + mImageQueue = LL::WorkQueue::getInstance("LLImageGL"); } //virtual @@ -703,6 +691,7 @@ void LLViewerTexture::cleanup() void LLViewerTexture::notifyAboutCreatingTexture() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { for(U32 f = 0; f < mNumFaces[ch]; f++) @@ -714,6 +703,7 @@ void LLViewerTexture::notifyAboutCreatingTexture() void LLViewerTexture::notifyAboutMissingAsset() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) { for(U32 f = 0; f < mNumFaces[ch]; f++) @@ -726,6 +716,7 @@ void LLViewerTexture::notifyAboutMissingAsset() // virtual void LLViewerTexture::dump() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLGLTexture::dump(); LL_INFOS() << "LLViewerTexture" @@ -761,6 +752,7 @@ bool LLViewerTexture::isActiveFetching() bool LLViewerTexture::bindDebugImage(const S32 stage) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (stage < 0) return false; bool res = true; @@ -779,6 +771,7 @@ bool LLViewerTexture::bindDebugImage(const S32 stage) bool LLViewerTexture::bindDefaultImage(S32 stage) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (stage < 0) return false; bool res = true; @@ -821,6 +814,7 @@ void LLViewerTexture::forceImmediateUpdate() void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) const { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(needs_gltexture) { mNeedsGLTexture = TRUE; @@ -831,14 +825,14 @@ void LLViewerTexture::addTextureStats(F32 virtual_size, BOOL needs_gltexture) co { //flag to reset the values because the old values are used. resetMaxVirtualSizeResetCounter(); - mMaxVirtualSize = virtual_size; - mAdditionalDecodePriority = 0.f; + mMaxVirtualSize = virtual_size; + mAdditionalDecodePriority = 0.f; mNeedsGLTexture = needs_gltexture; } else if (virtual_size > mMaxVirtualSize) { mMaxVirtualSize = virtual_size; - } + } } void LLViewerTexture::resetTextureStats() @@ -863,6 +857,7 @@ void LLViewerTexture::setKnownDrawSize(S32 width, S32 height) //virtual void LLViewerTexture::addFace(U32 ch, LLFace* facep) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); if(mNumFaces[ch] >= mFaceList[ch].size()) @@ -878,6 +873,7 @@ void LLViewerTexture::addFace(U32 ch, LLFace* facep) //virtual void LLViewerTexture::removeFace(U32 ch, LLFace* facep) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); if(mNumFaces[ch] > 1) @@ -918,6 +914,7 @@ S32 LLViewerTexture::getNumFaces(U32 ch) const //virtual void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mNumVolumes[ch] >= mVolumeList[ch].size()) { mVolumeList[ch].resize(2 * mNumVolumes[ch] + 1); @@ -931,6 +928,7 @@ void LLViewerTexture::addVolume(U32 ch, LLVOVolume* volumep) //virtual void LLViewerTexture::removeVolume(U32 ch, LLVOVolume* volumep) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if (mNumVolumes[ch] > 1) { S32 index = volumep->getIndexInTex(ch); @@ -954,6 +952,7 @@ S32 LLViewerTexture::getNumVolumes(U32 ch) const void LLViewerTexture::reorganizeFaceList() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static const F32 MAX_WAIT_TIME = 20.f; // seconds static const U32 MAX_EXTRA_BUFFER_SIZE = 4; @@ -977,6 +976,7 @@ void LLViewerTexture::reorganizeFaceList() void LLViewerTexture::reorganizeVolumeList() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static const F32 MAX_WAIT_TIME = 20.f; // seconds static const U32 MAX_EXTRA_BUFFER_SIZE = 4; @@ -1179,6 +1179,7 @@ FTType LLViewerFetchedTexture::getFTType() const void LLViewerFetchedTexture::cleanup() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -1204,6 +1205,7 @@ void LLViewerFetchedTexture::cleanup() //access the fast cache void LLViewerFetchedTexture::loadFromFastCache() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(!mInFastCacheList) { return; //no need to access the fast cache. @@ -1349,6 +1351,7 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. { return ; @@ -1365,6 +1368,7 @@ void LLViewerFetchedTexture::destroyTexture() void LLViewerFetchedTexture::addToCreateTexture() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; bool force_update = false; if (getComponents() != mRawImage->getComponents()) { @@ -1406,6 +1410,7 @@ void LLViewerFetchedTexture::addToCreateTexture() } else { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; #if 1 // //if mRequestedDiscardLevel > mDesiredDiscardLevel, we assume the required image res keep going up, @@ -1450,99 +1455,104 @@ void LLViewerFetchedTexture::addToCreateTexture() } } #endif - mNeedsCreateTexture = TRUE; - gTextureList.mCreateTextureList.insert(this); - } + scheduleCreateTexture(); + } return; } // ONLY called from LLViewerTextureList -BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) +BOOL LLViewerFetchedTexture::preCreateTexture(S32 usename/*= 0*/) { - if (!mNeedsCreateTexture) - { - destroyRawImage(); - return FALSE; - } - mNeedsCreateTexture = FALSE; - if (mRawImage.isNull()) - { - LL_ERRS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; - } - if (mRawImage->isBufferInvalid()) - { - LL_WARNS() << "Can't create a texture: invalid image data" << LL_ENDL; - destroyRawImage(); - return FALSE; - } -// LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", -// mRawDiscardLevel, -// mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) -// << mID.getString() << LL_ENDL; - BOOL res = TRUE; + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->checkActiveThread(); +#endif - // store original size only for locally-sourced images - if (mUrl.compare(0, 7, "file://") == 0) - { - mOrigWidth = mRawImage->getWidth(); - mOrigHeight = mRawImage->getHeight(); + if (!mNeedsCreateTexture) + { + destroyRawImage(); + return FALSE; + } + mNeedsCreateTexture = FALSE; + + if (mRawImage.isNull()) + { + LL_ERRS() << "LLViewerTexture trying to create texture with no Raw Image" << LL_ENDL; + } + if (mRawImage->isBufferInvalid()) + { + LL_WARNS() << "Can't create a texture: invalid image data" << LL_ENDL; + destroyRawImage(); + return FALSE; + } + // LL_INFOS() << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", + // mRawDiscardLevel, + // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) + // << mID.getString() << LL_ENDL; + BOOL res = TRUE; + + // store original size only for locally-sourced images + if (mUrl.compare(0, 7, "file://") == 0) + { + mOrigWidth = mRawImage->getWidth(); + mOrigHeight = mRawImage->getHeight(); // This is only safe because it's a local image and fetcher doesn't use raw data // from local images, but this might become unsafe in case of changes to fetcher - if (mBoostLevel == BOOST_PREVIEW) - { - mRawImage->biasedScaleToPowerOfTwo(1024); - } - else - { // leave black border, do not scale image content - mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); - } - - mFullWidth = mRawImage->getWidth(); - mFullHeight = mRawImage->getHeight(); - setTexelsPerImage(); - } - else - { - mOrigWidth = mFullWidth; - mOrigHeight = mFullHeight; - } + if (mBoostLevel == BOOST_PREVIEW) + { + mRawImage->biasedScaleToPowerOfTwo(1024); + } + else + { // leave black border, do not scale image content + mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); + } - bool size_okay = true; + mFullWidth = mRawImage->getWidth(); + mFullHeight = mRawImage->getHeight(); + setTexelsPerImage(); + } + else + { + mOrigWidth = mFullWidth; + mOrigHeight = mFullHeight; + } - S32 discard_level = mRawDiscardLevel; - if (mRawDiscardLevel < 0) - { - LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL; - discard_level = 0; - } + bool size_okay = true; - U32 raw_width = mRawImage->getWidth() << discard_level; - U32 raw_height = mRawImage->getHeight() << discard_level; + S32 discard_level = mRawDiscardLevel; + if (mRawDiscardLevel < 0) + { + LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL; + discard_level = 0; + } - if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE ) - { - LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; - size_okay = false; - } - - if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) - { - // A non power-of-two image was uploaded (through a non standard client) - LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; - size_okay = false; - } - - if( !size_okay ) - { - // An inappropriately-sized image was uploaded (through a non standard client) - // We treat these images as missing assets which causes them to - // be renderd as 'missing image' and to stop requesting data - LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; - setIsMissingAsset(); - destroyRawImage(); - return FALSE; - } + U32 raw_width = mRawImage->getWidth() << discard_level; + U32 raw_height = mRawImage->getHeight() << discard_level; + + if (raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE) + { + LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL; + size_okay = false; + } + + if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight())) + { + // A non power-of-two image was uploaded (through a non standard client) + LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL; + size_okay = false; + } + + if (!size_okay) + { + // An inappropriately-sized image was uploaded (through a non standard client) + // We treat these images as missing assets which causes them to + // be renderd as 'missing image' and to stop requesting data + LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL; + setIsMissingAsset(); + destroyRawImage(); + return FALSE; + } if (mGLTexturep->getHasExplicitFormat()) { @@ -1564,19 +1574,116 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) } } - res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + return res; +} - notifyAboutCreatingTexture(); +BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) +{ + if (!mNeedsCreateTexture) + { + return FALSE; + } - setActive(); + BOOL res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); + + return res; +} - if (!needsToSaveRawImage()) - { - mNeedsAux = FALSE; - destroyRawImage(); - } +void LLViewerFetchedTexture::postCreateTexture() +{ + if (!mNeedsCreateTexture) + { + return; + } +#if LL_IMAGEGL_THREAD_CHECK + mGLTexturep->checkActiveThread(); +#endif - return res; + notifyAboutCreatingTexture(); + + setActive(); + + if (!needsToSaveRawImage()) + { + mNeedsAux = FALSE; + destroyRawImage(); + } + + mNeedsCreateTexture = FALSE; +} + +void LLViewerFetchedTexture::scheduleCreateTexture() +{ + if (!mNeedsCreateTexture) + { + mNeedsCreateTexture = TRUE; + if (preCreateTexture()) + { +#if LL_IMAGEGL_THREAD_CHECK + //grab a copy of the raw image data to make sure it isn't modified pending texture creation + U8* data = mRawImage->getData(); + U8* data_copy = nullptr; + S32 size = mRawImage->getDataSize(); + if (data != nullptr && size > 0) + { + data_copy = new U8[size]; + memcpy(data_copy, data, size); + } +#endif + mNeedsCreateTexture = TRUE; + auto mainq = LLImageGLThread::sEnabled ? mMainQueue.lock() : nullptr; + if (mainq) + { + ref(); + mainq->postTo( + mImageQueue, + // work to be done on LLImageGL worker thread +#if LL_IMAGEGL_THREAD_CHECK + [this, data, data_copy, size]() + { + mGLTexturep->mActiveThread = LLThread::currentID(); + //verify data is unmodified + llassert(data == mRawImage->getData()); + llassert(mRawImage->getDataSize() == size); + llassert(memcmp(data, data_copy, size) == 0); +#else + [this]() + { +#endif + //actually create the texture on a background thread + createTexture(); + +#if LL_IMAGEGL_THREAD_CHECK + //verify data is unmodified + llassert(data == mRawImage->getData()); + llassert(mRawImage->getDataSize() == size); + llassert(memcmp(data, data_copy, size) == 0); +#endif + }, + // callback to be run on main thread +#if LL_IMAGEGL_THREAD_CHECK + [this, data, data_copy, size]() + { + mGLTexturep->mActiveThread = LLThread::currentID(); + llassert(data == mRawImage->getData()); + llassert(mRawImage->getDataSize() == size); + llassert(memcmp(data, data_copy, size) == 0); + delete[] data_copy; +#else + [this]() + { +#endif + //finalize on main thread + postCreateTexture(); + unref(); + }); + } + else + { + gTextureList.mCreateTextureList.insert(this); + } + } + } } // Call with 0,0 to turn this feature off. @@ -1868,6 +1975,7 @@ void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) void LLViewerFetchedTexture::updateVirtualSize() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; if(!mMaxVirtualSizeResetCounter) { addTextureStats(0.f, FALSE);//reset @@ -1959,6 +2067,7 @@ bool LLViewerFetchedTexture::isActiveFetching() bool LLViewerFetchedTexture::updateFetch() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false); static LLCachedControl<F32> sCameraMotionThreshold(gSavedSettings,"TextureCameraMotionThreshold", 0.2); static LLCachedControl<S32> sCameraMotionBoost(gSavedSettings,"TextureCameraMotionBoost", 3); @@ -2061,7 +2170,7 @@ bool LLViewerFetchedTexture::updateFetch() } else { - mIsRawImageValid = TRUE; + mIsRawImageValid = TRUE; addToCreateTexture(); } @@ -2539,6 +2648,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s bool LLViewerFetchedTexture::doLoadedCallbacks() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static const F32 MAX_INACTIVE_TIME = 900.f ; //seconds static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds @@ -2889,7 +2999,9 @@ void LLViewerFetchedTexture::destroyRawImage() //virtual void LLViewerFetchedTexture::switchToCachedImage() { - if(mCachedRawImage.notNull()) + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; + if(mCachedRawImage.notNull() && + !mNeedsCreateTexture) // <--- texture creation is pending, don't step on it { mRawImage = mCachedRawImage; @@ -2900,12 +3012,12 @@ void LLViewerFetchedTexture::switchToCachedImage() mComponents = mRawImage->getComponents(); mGLTexturep->setComponents(mComponents); gTextureList.dirtyImage(this); - } + } mIsRawImageValid = TRUE; mRawDiscardLevel = mCachedRawDiscardLevel; - gTextureList.mCreateTextureList.insert(this); - mNeedsCreateTexture = TRUE; + + scheduleCreateTexture(); } } @@ -3179,6 +3291,7 @@ bool LLViewerLODTexture::isUpdateFrozen() //virtual void LLViewerLODTexture::processTextureStats() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; updateVirtualSize(); static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes", false); @@ -3342,6 +3455,7 @@ bool LLViewerLODTexture::scaleDown() //static void LLViewerMediaTexture::updateClass() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; static const F32 MAX_INACTIVE_TIME = 30.f; #if 0 @@ -3518,11 +3632,22 @@ BOOL LLViewerMediaTexture::findFaces() for(; iter != obj_list->end(); ++iter) { LLVOVolume* obj = *iter; - if(obj->mDrawable.isNull()) - { - ret = FALSE; - continue; - } + if (obj->isDead()) + { + // Isn't supposed to happen, objects are supposed to detach + // themselves on markDead() + // If this happens, viewer is likely to crash + llassert(0); + LL_WARNS() << "Dead object in mMediaImplp's object list" << LL_ENDL; + ret = FALSE; + continue; + } + + if (obj->mDrawable.isNull() || obj->mDrawable->isDead()) + { + ret = FALSE; + continue; + } S32 face_id = -1; S32 num_faces = obj->mDrawable->getNumFaces(); |