diff options
| author | Dave Parks <davep@lindenlab.com> | 2009-12-11 14:50:45 -0600 | 
|---|---|---|
| committer | Dave Parks <davep@lindenlab.com> | 2009-12-11 14:50:45 -0600 | 
| commit | 35e2527230beacf8a545f8d609a61c80812bed32 (patch) | |
| tree | 2a5d250b34e1aded387fb06b109bbb4fe0a9bcb8 /indra | |
| parent | fadfa09e6d3bbff9ebae0aabeacf26a83aae4ad7 (diff) | |
| parent | 695969c77066de5032bdc9caefecf9b32b076b2f (diff) | |
merge
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/llcommon/llthread.cpp | 31 | ||||
| -rw-r--r-- | indra/llcommon/llthread.h | 22 | ||||
| -rw-r--r-- | indra/llmath/llvolume.cpp | 7 | ||||
| -rw-r--r-- | indra/llmath/llvolume.h | 2 | ||||
| -rw-r--r-- | indra/newview/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/newview/app_settings/settings.xml | 2 | ||||
| -rw-r--r-- | indra/newview/llappviewer.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llviewerregion.cpp | 1 | ||||
| -rw-r--r-- | indra/newview/llvovolume.cpp | 15 | ||||
| -rw-r--r-- | indra/newview/pipeline.cpp | 255 | ||||
| -rw-r--r-- | indra/newview/pipeline.h | 34 | 
11 files changed, 93 insertions, 286 deletions
| diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index b1175836b7..df7ea214cc 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -62,6 +62,9 @@  //   //---------------------------------------------------------------------------- +U32 ll_thread_local sThreadID = 0; +U32 LLThread::sIDIter = 0; +  //  // Handed to the APR thread creation function  // @@ -72,6 +75,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap  	// Set thread state to running  	threadp->mStatus = RUNNING; +	sThreadID = threadp->mID; +  	// Run the user supplied function  	threadp->run(); @@ -90,6 +95,8 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :  	mAPRThreadp(NULL),  	mStatus(STOPPED)  { +	mID = ++sIDIter; +  	// Thread creation probably CAN be paranoid about APR being initialized, if necessary  	if (poolp)  	{ @@ -273,7 +280,7 @@ void LLThread::wakeLocked()  //============================================================================  LLMutex::LLMutex(apr_pool_t *poolp) : -	mAPRMutexp(NULL) +	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)  {  	//if (poolp)  	//{ @@ -305,7 +312,14 @@ LLMutex::~LLMutex()  void LLMutex::lock()  { +	if (mLockingThread == sThreadID) +	{ //redundant lock +		mCount++; +		return; +	} +  	apr_thread_mutex_lock(mAPRMutexp); +	  #if MUTEX_DEBUG  	// Have to have the lock before we can access the debug info  	U32 id = LLThread::currentID(); @@ -313,10 +327,18 @@ void LLMutex::lock()  		llerrs << "Already locked in Thread: " << id << llendl;  	mIsLocked[id] = TRUE;  #endif + +	mLockingThread = sThreadID;  }  void LLMutex::unlock()  { +	if (mCount > 0) +	{ //not the root unlock +		mCount--; +		return; +	} +	  #if MUTEX_DEBUG  	// Access the debug info while we have the lock  	U32 id = LLThread::currentID(); @@ -324,6 +346,8 @@ void LLMutex::unlock()  		llerrs << "Not locked in Thread: " << id << llendl;	  	mIsLocked[id] = FALSE;  #endif + +	mLockingThread = NO_THREAD;  	apr_thread_mutex_unlock(mAPRMutexp);  } @@ -341,6 +365,11 @@ bool LLMutex::isLocked()  	}  } +U32 LLMutex::lockingThread() const +{ +	return mLockingThread; +} +  //============================================================================  LLCondition::LLCondition(apr_pool_t *poolp) : diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index d8aa90de2e..2d553b5258 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -40,8 +40,17 @@ class LLThread;  class LLMutex;  class LLCondition; +#if LL_WINDOWS
 +#define ll_thread_local __declspec(thread)
 +#else
 +#define ll_thread_local __thread
 +#endif +  class LL_COMMON_API LLThread  { +private: +	static U32 sIDIter; +  public:  	typedef enum e_thread_status  	{ @@ -82,6 +91,8 @@ public:  	apr_pool_t *getAPRPool() { return mAPRPoolp; }  	LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } +	U32 getID() const { return mID; } +  private:  	BOOL				mPaused; @@ -96,6 +107,7 @@ protected:  	apr_pool_t			*mAPRPoolp;  	BOOL				mIsLocalPool;  	EThreadStatus		mStatus; +	U32					mID;  	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.  	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. @@ -133,17 +145,27 @@ protected:  class LL_COMMON_API LLMutex  {  public: +	typedef enum +	{ +		NO_THREAD = 0xFFFFFFFF +	} e_locking_thread; +  	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex  	~LLMutex();  	void lock();		// blocks  	void unlock();  	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free +	U32 lockingThread() const; //get ID of locking thread  protected:  	apr_thread_mutex_t *mAPRMutexp; +	mutable U32			mCount; +	mutable U32			mLockingThread; +	  	apr_pool_t			*mAPRPoolp;  	BOOL				mIsLocalPool; +	S32					mLockCount;  #if MUTEX_DEBUG  	std::map<U32, BOOL> mIsLocked;  #endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index fb2de92e35..44ff173502 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -1952,8 +1952,12 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)  	}  	is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); -	 +	return unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger()); +} + +BOOL LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +{  	U8* result = NULL;  	U32 cur_size = 0; @@ -1964,7 +1968,6 @@ BOOL LLVolume::createVolumeFacesFromStream(std::istream& is)  		const U32 CHUNK = 65536; -		S32 size = header[nm[lod]]["size"].asInteger();  		U8 *in = new U8[size];  		is.read((char*) in, size);  diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 59c60ccd92..9970b24a94 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -971,6 +971,8 @@ protected:  public:  	virtual BOOL createVolumeFacesFromFile(const std::string& file_name);  	virtual BOOL createVolumeFacesFromStream(std::istream& is); +	virtual BOOL unpackVolumeFaces(std::istream& is, S32 size); +  	virtual void makeTetrahedron();  	virtual BOOL isTetrahedron(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 7cbdff38dd..413b9bb438 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -284,6 +284,7 @@ set(viewer_SOURCE_FILES      llmediaremotectrl.cpp      llmemoryview.cpp      llmenucommands.cpp +    llmeshrepository.cpp      llmetricperformancetester.cpp      llmimetypes.cpp      llmorphview.cpp @@ -792,6 +793,7 @@ set(viewer_HEADER_FILES      llmediaremotectrl.h      llmemoryview.h      llmenucommands.h +    llmeshrepository.h      llmetricperformancetester.h      llmimetypes.h      llmorphview.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e889c552aa..a4142b41b0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -10009,7 +10009,7 @@        <key>Type</key>        <string>Boolean</string>        <key>Value</key> -      <integer>1</integer> +      <integer>0</integer>      </map>      <key>UseStartScreen</key>      <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 508badcc6f..e856987726 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -48,6 +48,7 @@  #include "llwindow.h"  #include "llviewerstats.h"  #include "llmd5.h" +#include "llmeshrepository.h"  #include "llpumpio.h"  #include "llmimetypes.h"  #include "llslurl.h" @@ -1263,6 +1264,9 @@ bool LLAppViewer::cleanup()  	llinfos << "Cleaning Up" << llendflush; +	// shut down mesh streamer +	gMeshRepo.shutdown(); +  	// Must clean up texture references before viewer window is destroyed.  	LLHUDManager::getInstance()->updateEffects();  	LLHUDObject::updateAll(); @@ -1675,6 +1679,9 @@ bool LLAppViewer::initThreads()  		mFastTimerLogThread->start();  	} +	// Mesh streaming and caching +	gMeshRepo.init(); +  	// *FIX: no error handling here!  	return true;  } @@ -2391,6 +2398,7 @@ bool LLAppViewer::initWindow()  		gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );  		gPipeline.init(); +		  		stop_glerror();  		gViewerWindow->initGLDefaults(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 8317837520..f173149bf4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1432,6 +1432,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)  	capabilityNames.append("FetchLib");  	capabilityNames.append("FetchLibDescendents");  	capabilityNames.append("GetTexture"); +	capabilityNames.append("GetMesh");  	capabilityNames.append("GroupProposalBallot");  	capabilityNames.append("HomeLocation");  	capabilityNames.append("MapLayer"); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 7debfb9186..f66f0c2d72 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -70,6 +70,7 @@  #include "llsdutil.h"  #include "llmediaentry.h"  #include "llmediadataclient.h" +#include "llmeshrepository.h"  #include "llagent.h"  const S32 MIN_QUIET_FRAMES_COALESCE = 30; @@ -861,6 +862,16 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  {  	LLVolumeParams volume_params = params; +	if (isSculpted()) +	{ +		// if it's a mesh +		if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) +		{ //meshes might not have all LODs, get the force detail to best existing LOD +			LLUUID mesh_id = params.getSculptID(); +			mLOD = gMeshRepo.getActualMeshLOD(mesh_id, mLOD); +		} +	} +  	// Check if we need to change implementations  	bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE);  	if (is_flexible) @@ -888,6 +899,8 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  		}  	} +	 +  	if ((LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged)  	{  		mFaceMappingChanged = TRUE; @@ -906,7 +919,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms, const S32 detail, bool  				{   					//load request not yet issued, request pipeline load this mesh  					LLUUID asset_id = volume_params.getSculptID(); -					gPipeline.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail())); +					gMeshRepo.loadMesh(this, asset_id, LLVolumeLODGroup::getVolumeDetailFromScale(getVolume()->getDetail()));  				}  			}  			else // otherwise is sculptie diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 610804c5eb..b37645d2de 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -70,6 +70,7 @@  #include "llgldbg.h"  #include "llhudmanager.h"  #include "lllightconstants.h" +#include "llmeshrepository.h"  #include "llresmgr.h"  #include "llselectmgr.h"  #include "llsky.h" @@ -103,6 +104,7 @@  #include "llspatialpartition.h"  #include "llmutelist.h"  #include "lltoolpie.h" +#include "llcurl.h"  #ifdef _DEBUG @@ -342,8 +344,6 @@ LLPipeline::LLPipeline() :  	mGlowPool(NULL),  	mBumpPool(NULL),  	mWLSkyPool(NULL), -	mMeshMutex(NULL), -	mMeshThreadCount(0),  	mLightMask(0),  	mLightMovingMask(0),  	mLightingDetail(0), @@ -403,7 +403,6 @@ void LLPipeline::init()  	stop_glerror(); -	mMeshMutex = new LLMutex(NULL);  	for (U32 i = 0; i < 2; ++i)  	{  		mSpotLightFade[i] = 1.f; @@ -478,9 +477,6 @@ void LLPipeline::cleanup()  	//delete mWLSkyPool;  	mWLSkyPool = NULL; -	delete mMeshMutex; -	mMeshMutex = NULL; -  	releaseGLBuffers();  	mBloomImagep = NULL; @@ -1802,6 +1798,8 @@ void LLPipeline::rebuildPriorityGroups()  	assertInitialized(); +	gMeshRepo.notifyLoadedMeshes(); +  	// Iterate through all drawables on the priority build queue,  	for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin();  		 iter != mGroupQ1.end(); ++iter) @@ -1881,8 +1879,6 @@ void LLPipeline::updateGeom(F32 max_dtime)  	// for now, only LLVOVolume does this to throttle LOD changes  	LLVOVolume::preUpdateGeom(); -	notifyLoadedMeshes(); -  	// Iterate through all drawables on the priority build queue,  	for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin();  		 iter != mBuildQ1.end();) @@ -8912,246 +8908,3 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()  } -void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail) -{ -	if (detail < 0 || detail > 4) -	{ -		return; -	} - -	{ -		LLMutexLock lock(mMeshMutex); -		//add volume to list of loading meshes -		mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); -		if (iter != mLoadingMeshes[detail].end()) -		{ //request pending for this mesh, append volume id to list -			iter->second.insert(vobj->getID()); -			return; -		} - -		//first request for this mesh -		mLoadingMeshes[detail][mesh_id].insert(vobj->getID()); -	} - -	if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH)) -	{ //already have asset, load desired LOD in background -		mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume(), detail)); -	} -	else -	{ //fetch asset and load when done -		gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH, -									getMeshAssetCallback, vobj->getVolume(), TRUE); -	} - -	//do a quick search to see if we can't display something while we wait for this mesh to load -	LLVolume* volume = vobj->getVolume(); - -	if (volume) -	{ -		LLVolumeParams params = volume->getParams(); - -		LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); - -		if (group) -		{ -			//first see what the next lowest LOD available might be -			for (S32 i = detail-1; i >= 0; --i) -			{ -				LLVolume* lod = group->refLOD(i); -				if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) -				{ -					volume->copyVolumeFaces(lod); -					group->derefLOD(lod); -					return; -				} - -				group->derefLOD(lod); -			} - -			//no lower LOD is a available, is a higher lod available? -			for (S32 i = detail+1; i < 4; ++i) -			{ -				LLVolume* lod = group->refLOD(i); -				if (lod && !lod->isTetrahedron() && lod->getNumVolumeFaces() > 0) -				{ -					volume->copyVolumeFaces(lod); -					group->derefLOD(lod); -					return; -				} - -				group->derefLOD(lod); -			} -		} -		else -		{ -			llerrs << "WTF?" << llendl; -		} - -		//nothing found, so make a tetrahedron -		volume->makeTetrahedron(); -	} -} - -//static -void LLPipeline::getMeshAssetCallback(LLVFS *vfs, -										  const LLUUID& asset_uuid, -										  LLAssetType::EType type, -										  void* user_data, S32 status, LLExtStat ext_status) -{ -	gPipeline.mPendingMeshes.push_back(new LLMeshThread(asset_uuid, (LLVolume*) user_data)); -} - - -LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail) -: LLThread("mesh_loading_thread") -{ -	mMeshID = mesh_id; -	mVolume = NULL; -	mDetail = target->getDetail(); - -	if (detail == -1) -	{ -		mDetailIndex = LLVolumeLODGroup::getVolumeDetailFromScale(target->getDetail()); -	} -	else -	{ -		mDetailIndex = detail; -	} - -	mTargetVolume = target; -} - -LLPipeline::LLMeshThread::~LLMeshThread() -{ - -} - -void LLPipeline::LLMeshThread::run() -{ -	if (!gAssetStorage || LLApp::instance()->isQuitting()) -	{ -		return; -	} - -	char* buffer = NULL; -	S32 size = 0; -	 -	LLVFS* vfs = gAssetStorage->mVFS; - -	{ -		LLVFile file(vfs, mMeshID, LLAssetType::AT_MESH, LLVFile::READ); -		file.waitForLock(VFSLOCK_READ); -		size = file.getSize(); -		 -		if (size == 0) -		{ -			gPipeline.meshLoaded(this); -			return; -		} -		 -		buffer = new char[size]; -		file.read((U8*)&buffer[0], size); -	} - -	{ -		std::string buffer_string(buffer, size); -		std::istringstream buffer_stream(buffer_string); - -		{ -			LLVolumeParams volume_params; -			volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); -			volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH); -			mVolume = new LLVolume(volume_params, mDetail); -			mVolume->createVolumeFacesFromStream(buffer_stream); -		} -	} -	delete[] buffer; -	 -	gPipeline.meshLoaded(this); -} - -void LLPipeline::meshLoaded(LLPipeline::LLMeshThread* mesh_thread) -{ -	LLMutexLock lock(mMeshMutex); -	mLoadedMeshes.push_back(mesh_thread); -} - -void LLPipeline::notifyLoadedMeshes() -{ //called from main thread - -	U32 max_thread_count = llmax(gSavedSettings.getU32("MeshThreadCount"), (U32) 1); -	while (mMeshThreadCount < max_thread_count && !mPendingMeshes.empty()) -	{ -		LLMeshThread* mesh_thread = mPendingMeshes.front(); -		mesh_thread->start(); -		++mMeshThreadCount; -		mPendingMeshes.pop_front(); -	} - -	LLMutexLock lock(mMeshMutex); -	std::list<LLMeshThread*> stopping_threads; - -	for (std::list<LLMeshThread*>::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter) -	{ //for each mesh done loading -		LLMeshThread* mesh = *iter; -		 -		if (!mesh->isStopped()) -		{ //don't process a LLMeshThread until it's stopped -			stopping_threads.push_back(mesh); -			continue; -		} - -		S32 detail = mesh->mDetailIndex; - -		//get list of objects waiting to be notified this mesh is loaded -		mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh->mMeshID); - -		if (mesh->mVolume && obj_iter != mLoadingMeshes[detail].end()) -		{ -			//make sure target volume is still valid -			BOOL valid = FALSE; - -			for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) -			{ -				LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); - -				if (vobj) -				{ -					if (vobj->getVolume() == mesh->mTargetVolume) -					{ -						valid = TRUE; -					} -				} -			} - - -			if (valid) -			{ -				if (mesh->mVolume->getNumVolumeFaces() <= 0) -				{ -					llwarns << "Mesh loading returned empty volume." << llendl; -					mesh->mVolume->makeTetrahedron(); -				} -				 -				mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume); - -				for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) -				{ -					LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); -					if (vobj) -					{ -						vobj->notifyMeshLoaded(); -					} -				} -			} - -			mLoadingMeshes[detail].erase(mesh->mMeshID); -		} - -		delete mesh; -		--mMeshThreadCount; -	} - -	mLoadedMeshes = stopping_threads; -} - diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index f41f6173a9..0b040acf51 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -58,6 +58,8 @@ class LLCubeMap;  class LLCullResult;  class LLVOAvatar;  class LLGLSLShader; +class LLCurlRequest; +class LLMeshResponder;  typedef enum e_avatar_skinning_method  { @@ -278,10 +280,6 @@ public:  	LLCullResult::sg_list_t::iterator beginAlphaGroups();  	LLCullResult::sg_list_t::iterator endAlphaGroups(); - -	//mesh management functions -	void loadMesh(LLVOVolume* volume, LLUUID mesh_id, S32 detail = 0); -	  	void addTrianglesDrawn(S32 count);  	BOOL hasRenderType(const U32 type) const				{ return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; }  	BOOL hasRenderDebugFeatureMask(const U32 mask) const	{ return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } @@ -683,32 +681,8 @@ protected:  	typedef std::map<LLUUID, std::set<LLUUID> > mesh_load_map;  	mesh_load_map mLoadingMeshes[4]; -	LLMutex*					mMeshMutex; - -	class LLMeshThread : public LLThread -	{ -	public: -		LLPointer<LLVolume> mVolume; -		LLVolume* mTargetVolume; -		LLUUID mMeshID; -		F32 mDetail; -		S32 mDetailIndex; -		LLMeshThread(LLUUID mesh_id, LLVolume* target, S32 detail = -1); -		~LLMeshThread(); -		void run(); -	}; -	 -	static void getMeshAssetCallback(LLVFS *vfs, -										  const LLUUID& asset_uuid, -										  LLAssetType::EType type, -										  void* user_data, S32 status, LLExtStat ext_status); - -	std::list<LLMeshThread*> mLoadedMeshes; -	std::list<LLMeshThread*> mPendingMeshes; -	U32 mMeshThreadCount; - -	void meshLoaded(LLMeshThread* mesh_thread); -	void notifyLoadedMeshes(); +	typedef std::list<LLMeshResponder*> mesh_response_list; +	mesh_response_list			mMeshResponseList;  	LLPointer<LLViewerFetchedTexture>	mFaceSelectImagep;  	LLPointer<LLViewerTexture>	mBloomImagep; | 
