diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 55d0c85cbd..e1876599fc 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -29,9 +29,25 @@ #include "llerror.h" +#if LL_REF_COUNT_DEBUG +#include "llthread.h" +#include "llapr.h" +#endif + LLRefCount::LLRefCount(const LLRefCount& other) : mRef(0) { +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + mMutexp = new LLMutex(gAPRPoolp) ; + } + else + { + mMutexp = NULL ; + } + mCrashAtUnlock = FALSE ; +#endif } LLRefCount& LLRefCount::operator=(const LLRefCount&) @@ -43,6 +59,17 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&) LLRefCount::LLRefCount() : mRef(0) { +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + mMutexp = new LLMutex(gAPRPoolp) ; + } + else + { + mMutexp = NULL ; + } + mCrashAtUnlock = FALSE ; +#endif } LLRefCount::~LLRefCount() @@ -51,4 +78,87 @@ LLRefCount::~LLRefCount() { llerrs << "deleting non-zero reference" << llendl; } + +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + delete mMutexp ; + } +#endif } + +#if LL_REF_COUNT_DEBUG +void LLRefCount::ref() const +{ + if(mMutexp) + { + if(mMutexp->isLocked()) + { + mCrashAtUnlock = TRUE ; + llerrs << "the mutex is locked by the thread: " << mLockedThreadID + << " Current thread: " << LLThread::currentID() << llendl ; + } + + mMutexp->lock() ; + mLockedThreadID = LLThread::currentID() ; + + mRef++; + + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + } + else + { + mRef++; + } +} + +S32 LLRefCount::unref() const +{ + if(mMutexp) + { + if(mMutexp->isLocked()) + { + mCrashAtUnlock = TRUE ; + llerrs << "the mutex is locked by the thread: " << mLockedThreadID + << " Current thread: " << LLThread::currentID() << llendl ; + } + + mMutexp->lock() ; + mLockedThreadID = LLThread::currentID() ; + + llassert(mRef >= 1); + if (0 == --mRef) + { + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + + delete this; + return 0; + } + + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + return mRef; + } + else + { + llassert(mRef >= 1); + if (0 == --mRef) + { + delete this; + return 0; + } + return mRef; + } +} +#endif diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 19f008b15c..693c1c4b83 100644 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -28,6 +28,11 @@ #include +#define LL_REF_COUNT_DEBUG 0 +#if LL_REF_COUNT_DEBUG +class LLMutex ; +#endif + //---------------------------------------------------------------------------- // RefCount objects should generally only be accessed by way of LLPointer<>'s // see llthread.h for LLThreadSafeRefCount @@ -43,12 +48,16 @@ protected: public: LLRefCount(); - void ref() const +#if LL_REF_COUNT_DEBUG + void ref() const ; + S32 unref() const ; +#else + inline void LLRefCount::ref() const { mRef++; } - S32 unref() const + inline S32 LLRefCount::unref() const { llassert(mRef >= 1); if (0 == --mRef) @@ -58,6 +67,7 @@ public: } return mRef; } +#endif //NOTE: when passing around a const LLRefCount object, this can return different results // at different types, since mRef is mutable @@ -68,6 +78,12 @@ public: private: mutable S32 mRef; + +#if LL_REF_COUNT_DEBUG + LLMutex* mMutexp ; + mutable U32 mLockedThreadID ; + mutable BOOL mCrashAtUnlock ; +#endif }; #endif diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index a1c2265f62..05a4b245d1 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1609,6 +1609,35 @@ void LLModelLoader::run() } } +//called in the main thread +void LLModelLoader::loadTextures() +{ + BOOL is_paused = isPaused() ; + pause() ; //pause the loader + + for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) + { + for(U32 i = 0 ; i < iter->second.size(); i++) + { + for(U32 j = 0 ; j < iter->second[i].mMaterial.size() ; j++) + { + if(!iter->second[i].mMaterial[j].mDiffuseMapFilename.empty()) + { + iter->second[i].mMaterial[j].mDiffuseMap = + LLViewerTextureManager::getFetchedTextureFromUrl("file://" + iter->second[i].mMaterial[j].mDiffuseMapFilename, TRUE, LLViewerTexture::BOOST_PREVIEW); + iter->second[i].mMaterial[j].mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); + iter->second[i].mMaterial[j].mDiffuseMap->forceToSaveRawImage(); + } + } + } + } + + if(!is_paused) + { + unpause() ; + } +} + bool LLModelLoader::isNodeAJoint( domNode* pNode ) { if ( pNode->getName() == NULL) @@ -1914,14 +1943,8 @@ LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) // we only support init_from now - embedded data will come later domImage::domInit_from* init = image->getInit_from(); if (init) - { - std::string filename = cdom::uriToNativePath(init->getValue().str()); - - mat.mDiffuseMap = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + filename, TRUE, LLViewerTexture::BOOST_PREVIEW); - mat.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, this->mPreview, NULL, FALSE); - - mat.mDiffuseMap->forceToSaveRawImage(); - mat.mDiffuseMapFilename = filename; + { + mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); mat.mDiffuseMapLabel = getElementLabel(material); } } @@ -2377,6 +2400,7 @@ void LLModelPreview::loadModelCallback(S32 lod) return; } + mModelLoader->loadTextures() ; mModel[lod] = mModelLoader->mModelList; mScene[lod] = mModelLoader->mScene; mVertexBuffer[lod].clear(); @@ -3819,7 +3843,7 @@ BOOL LLModelPreview::render() gGL.getTexUnit(0)->bind(instance.mMaterial[i].mDiffuseMap, true); if (instance.mMaterial[i].mDiffuseMap->getDiscardLevel() > -1) { - mTextureSet.insert(instance.mMaterial[i].mDiffuseMap); + mTextureSet.insert(instance.mMaterial[i].mDiffuseMap.get()); } } } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 11c2447da5..52ebec84d0 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -97,6 +97,7 @@ public: virtual void run(); + void loadTextures() ; //called in the main thread. void processElement(daeElement* element); std::vector getMaterials(LLModel* model, domInstance_geometry* instance_geo); LLImportMaterial profileToMaterial(domProfile_COMMON* material); @@ -325,7 +326,7 @@ class LLModelPreview : public LLViewerDynamicTexture, public LLMutex std::map, std::vector > > mPhysicsMesh; LLMeshUploadThread::instance_list mUploadData; - std::set > mTextureSet; + std::set mTextureSet; //map of vertex buffers to models (one vertex buffer in vector per face in model std::map > > mVertexBuffer[LLModel::NUM_LODS+1]; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index dd2dcffc28..d2f76eceb0 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -1450,17 +1450,21 @@ void LLMeshUploadThread::DecompRequest::completed() mThread->mHullMap[mBaseModel] = mHull[0]; } -void LLMeshUploadThread::run() +//called in the main thread. +void LLMeshUploadThread::preStart() { - mCurlRequest = new LLCurlRequest(); - //build map of LLModel refs to instances for callbacks for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter) { mInstance[iter->mModel].push_back(*iter); } +} - std::set > textures; +void LLMeshUploadThread::run() +{ + mCurlRequest = new LLCurlRequest(); + + std::set textures; //populate upload queue with relevant models for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) @@ -1483,9 +1487,9 @@ void LLMeshUploadThread::run() material_iter != instance.mMaterial.end(); ++material_iter) { - if (textures.find(material_iter->mDiffuseMap) == textures.end()) + if (textures.find(material_iter->mDiffuseMap.get()) == textures.end()) { - textures.insert(material_iter->mDiffuseMap); + textures.insert(material_iter->mDiffuseMap.get()); LLTextureUploadData data(material_iter->mDiffuseMap.get(), material_iter->mDiffuseMapLabel); uploadTexture(data); @@ -2148,6 +2152,7 @@ S32 LLMeshRepository::update() for (S32 i = 0; i < size; ++i) { mUploads.push_back(mUploadWaitList[i]); + mUploadWaitList[i]->preStart() ; mUploadWaitList[i]->start() ; } mUploadWaitList.clear() ; diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 8c9892b28f..eccb82b661 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -431,6 +431,7 @@ public: bool finished() { return mFinished; } virtual void run(); + void preStart(); }; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 10126219f8..b5eadb6d25 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -834,7 +834,7 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) for (entries_list_t::iterator iter3 = entries.begin(); iter3 != entries.end(); ) { - LLPointer imagep = *iter3++; + LLViewerFetchedTexture* imagep = *iter3++; bool fetching = imagep->updateFetch(); if (fetching)